2

I need to use a random number generator very often, and instead of writing it everytime I need it I would like to make a class so that I can just link it into other programs. The current code I have is this:

#include <boost/random.hpp>
#include <iostream>
int main() {
   boost::mt19937 rng(0);
   boost::normal_distribution<float> dist_normal(0.0f,1.0f);
   boost::variate_generator<boost::mt19937, boost::normal_distribution<float> > rand_normal(rng, dist_normal);

   for(int i = 0 ; i < 10; ++i)
      std::cout << rand_normal() << std::endl;
   return 0;
}

But now I would like to separate interface and implementation like so:

#include <boost/random.hpp>
#include <iostream>
int main() {
   //This goes in the header file as private members of class
   boost::mt19937 rng;
   boost::normal_distribution<float> dist_normal;
   boost::variate_generator<boost::mt19937, boost::normal_distribution<float> > rand_normal;

   //This is then in the constructor in the cpp file
   rng = boost::mt19937(0);
   dist_normal  = boost::normal_distribution<float>(0.0f,1.0f);
   rand_normal  = boost::variate_generator<boost::mt19937, boost::normal_distribution<float> >(rng, dist_normal);

   for(int i = 0 ; i < 10; ++i)
      std::cout << rand_normal() << std::endl;
   return 0;
}

But this does not compile, it gives me the following errors (oh the joy of deciphering boost errors):

test2.cpp: In function ‘int main()’:
test2.cpp:7:79: error: no matching function for call to ‘boost::random::variate_generator<boost::random::mersenne_twister_engine<unsigned int, 32ul, 624ul, 397ul, 31ul, 2567483615u, 11ul, 4294967295u, 7ul, 2636928640u, 15ul, 4022730752u, 18ul, 1812433253u>, boost::random::normal_distribution<float> >::variate_generator()’
test2.cpp:7:79: note: candidates are:
/usr/include/boost/random/variate_generator.hpp:69:5: note: boost::random::variate_generator<Engine, Distribution>::variate_generator(Engine, Distribution) [with Engine = boost::random::mersenne_twister_engine<unsigned int, 32ul, 624ul, 397ul, 31ul, 2567483615u, 11ul, 4294967295u, 7ul, 2636928640u, 15ul, 4022730752u, 18ul, 1812433253u>, Distribution = boost::random::normal_distribution<float>]
/usr/include/boost/random/variate_generator.hpp:69:5: note:   candidate expects 2 arguments, 0 provided
/usr/include/boost/random/variate_generator.hpp:51:7: note: boost::random::variate_generator<boost::random::mersenne_twister_engine<unsigned int, 32ul, 624ul, 397ul, 31ul, 2567483615u, 11ul, 4294967295u, 7ul, 2636928640u, 15ul, 4022730752u, 18ul, 1812433253u>, boost::random::normal_distribution<float> >::variate_generator(const boost::random::variate_generator<boost::random::mersenne_twister_engine<unsigned int, 32ul, 624ul, 397ul, 31ul, 2567483615u, 11ul, 4294967295u, 7ul, 2636928640u, 15ul, 4022730752u, 18ul, 1812433253u>, boost::random::normal_distribution<float> >&)
/usr/include/boost/random/variate_generator.hpp:51:7: note:   candidate expects 1 argument, 0 provided

And here I am stuck, from what I understand the second candidate is the copy constructor, but how should I read the first candidate and how should I change my code such that it works? Thanks in advance!

EDIT:

The working solution, thanks to muehlbau.

boost_rng.c:

#include "boost_rng.hpp"

BoostRNG::BoostRNG(uint _seed) : seed(_seed), 
                                 rng(boost::mt19937(_seed)),
                                 dist_normal(boost::normal_distribution<float>(0.0f,1.0f)),
                                 rand_normal(boost::variate_generator<boost::mt19937&, boost::normal_distribution<float> >(rng, dist_normal))
{}

float BoostRNG::normal() {
    return rand_normal();
}

and boost_rng.hpp:

#include <boost/random.hpp>

class BoostRNG {
private:
    uint seed;
    boost::mt19937 rng;
    boost::normal_distribution<float> dist_normal;
    boost::variate_generator<boost::mt19937&, boost::normal_distribution<float> > rand_normal;
public:
    BoostRNG(uint seed);
    float normal();
};

Note that it works for references the the engine as well, letting me use the same engine for multiple generators ;)

4

1 に答える 1

2

問題は次のとおりです。rngdist_normal、およびを宣言するとrand_normalboost::mt19937boost::normal_distribution<float>、およびboost::variate_generator<boost::mt19937, boost::normal_distribution<float> >オブジェクトがそれぞれ構築されます。エラーからわかる限りboost::variate_generator<boost::mt19937, boost::normal_distribution<float> >、デフォルトのコンストラクターがないため、コンパイルは失敗します。

ここで解決策を探すことができます: c++ で初期化する前にオブジェクトを宣言する

補足として...いつでもクラスを作成し、クラスメンバーとして、、、を持ち、rngクラスコンストラクターの初期化子リストでそれらを初期化できます。dist_normalrand_normal

于 2012-10-19T12:44:40.117 に答える