Boost generic programming

H

Hans Mull

Hi!
I'm working on a random number generator which makes use of
Boost::random. I have to write a function that gets 2 int-parameters
from the GUI. One is a number that indicates which algorithm to use and
the other shows which distribution we have to use. Boost uses templates
so I cannot use polymorphism (Or is there a way to use polymorphism even
if the classes aren't derivated from a base class?). I tried to use a
template function, but I don't know the types when I call the fuction
(xxParam are static variables):

template<class boostEngine, class boostDistribution>
void GenRandBoost()
{
///Cache parameters
ulong amount = amountParam;
ulong ulSeed = seedParam;
string filename = filenameParam;
double ulDouble = ulDoubleParam;
double llDouble = llDoubleParam;
int distributionSelection = distributionSelectionParam;
int algorithmSelection = algorithmSelectionParam;
ulong bits = bitsParam;

///Initialize template pointers
boostEngine *algorithm;
boostDistribution *distribution;


///Open fstream
fstream f(filename.c_str(), fstream::eek:ut);
//Initialize counter
ulong i;

///Switch distribution
switch(algorithmSelection)
{
case 0: ///MT 19937
{
mt19937 mersenne(ulSeed);
algorithm = &mersenne;
break;
}
case 1: ///Linear congruential
{
minstd_rand0 linCongr(ulSeed);
algorithm = &linCongr;
break;
}
case 2: ///Additive combine
{
ecuyer1988 addComb(ulSeed);
algorithm = &addComb;
break;
}
case 3: ///Inverse congruential
{
hellekalek1995 invCongr(ulSeed);
algorithm = &invCongr;
break;
}
case 4: ///Shuffle output
{
kreutzer1986 shOut(ulSeed);
algorithm = &shOut;
break;
}
// case 5: ///Lagged Fibonacci
// {
// lagged_fibonacci lagFib(ulSeed);
// algorithm = &lagFib;
// break;
// }
default: break;
}
///Switch distribution
switch(distributionSelection)
{
case 0: ///Uniform small int
{
uniform_smallint<double> smallInt(llDouble, ulDouble);
distribution = &smallInt;
}
case 1: ///Uniform integer
{
uniform_int<double> uniInt(llDouble, ulDouble);
distribution = &uniInt;
}
case 2: ///Uniform 01
{
//uniform_01<double, double> uni01(llDouble, ulDouble);
//distribution = &uni01;
}
case 3: ///Uniform real
{
uniform_real<double> uniReal(llDouble, ulDouble);
distribution = &uniReal;

}
case 4: ///Triangle
{
triangle_distribution<double> triangle(llDouble,
ulDouble);
distribution = &triangle;
}
case 5: ///Bernoulli
{
bernoulli_distribution<double> bernoulli(llDouble,
ulDouble);
distribution = &bernoulli;
}
case 6: ///Cauchy
{
cauchy_distribution<double> cauchy(llDouble, ulDouble);
distribution = &cauchy;
}
case 7: ///Exponential
{
exponential_distribution<double>
exponential(llDouble, ulDouble);
distribution = &exponential;
}
case 8: ///Geometric
{
geometric_distribution<double> geometric(llDouble,
ulDouble);
distribution = &geometric;
}
case 9: ///Normal
{
normal_distribution<double> normal(llDouble, ulDouble);
distribution = &normal;
}
case 10: ///Lognormal
{
lognormal_distribution<double> lognormal(llDouble,
ulDouble);
distribution = &lognormal;
}
case 11: ///Uniform on Sphere
{
uniform_on_sphere<double> uniSphere(llDouble, ulDouble);
distribution = &uniSphere;
}
default: {break;}
}
///Variate Generator
variate_generator<boostEngine, boostDistribution>
generator(algorithm, distribution);
///TODO: Main loop
for(;i < amount;i++)
{
f << generator() << endl;
}
}

I don't want to have a distributionSelection switch in each
algorithmSelection case statement.

Do you have any ideas?

Thanks in advance, Hans
 
M

Martin York

Have not looked at everything but I suspect that you are using objects
after they have been destroyed:

case 0: ///MT 19937
{
mt19937 mersenne(ulSeed);
algorithm = &mersenne;
break;
}

Here the object mersenne is destroyed when it goes out of scope.
Thus algorithm is left as a dangling pointer to some random piece of
memory (That will probably be re-used by another object very soon).

You can't use template functions to determine something at runtime. As
the template instantiation is done at compile time. So a switch is
your best option. Though personally I would move the switch into
another object (FactoryPattern) thus keeping this method cleaner and
easier to read.
 
C

Cholo Lennon

Have not looked at everything but I suspect that you are using objects
after they have been destroyed:

case 0: ///MT 19937
{
mt19937 mersenne(ulSeed);
algorithm = &mersenne;
break;
}

Here the object mersenne is destroyed when it goes out of scope.
Thus algorithm is left as a dangling pointer to some random piece of
memory (That will probably be re-used by another object very soon).

You can't use template functions to determine something at runtime. As
the template instantiation is done at compile time. So a switch is
your best option. Though personally I would move the switch into
another object (FactoryPattern) thus keeping this method cleaner and
easier to read.

Also the OP should evaluate the Strategy Pattern.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,962
Messages
2,570,134
Members
46,690
Latest member
MacGyver

Latest Threads

Top