Re: How to adapt static polymorphic classes to dynamic polymorphic behavior?
On Dec 26, 12:32 am, terminator <farid.mehr...@gmail.com> wrote:
On Dec 25, 1:38 am, "marco.guazz...@gmail.com"
<marco.guazz...@gmail.com> wrote:
NOTE: if you want I post the entire source code. I didn't do it since
this post is already very long.
I think everybody agrees on this one.
There is too much stuff,making it incomprehencible.
Thanks for the advice. Here below is the sample code. Hope this makes
my problem clearer.
Note: my aim is to wrap third party probability distributions
libraries (represented by namespace "lib", in the code below) into
dynamic polymorphic classes (represented by namespace "my", in the
code below) in order to take advantage of runtime polymorphism and
hence to choose what probability/random generator to use at runtime
and to create vector of different probability distributions (see the
"main" function for an example).
Thank you very much for any hints!!!
--- [code] ---
#include <iostream>
#include <stdint.h>
#include <vector>
namespace lib {
/// "lib" contains untouchable classes
/// RANDOM NUMBER GENERATORS
template <typename ResultT, ResultT a, ResultT c, ResultT m>
struct linear_congruential
{
typedef ResultT result_type;
linear_congruential(result_type seed=1)
: x_(seed)
{
}
result_type operator()()
{
return x_ = (x_*a + c) % m;
}
result_type x_;
};
typedef linear_congruential<uint32_t, 48271, 0, 2147483647> minstd;
/// PROBABILITY DISTRIBUTIONS
template <typename RealT=double>
struct exponential
{
typedef RealT real_type;
exponential(real_type lambda)
: lambda_(lambda)
{
}
real_type lambda_;
};
template <typename RealT=double>
struct normal
{
typedef RealT real_type;
normal(real_type mean, real_type sd)
: mean_(mean),
sd_(sd)
{
}
real_type mean_;
real_type sd_;
};
/// Free polymorphic functions
template <typename RealT, typename GeneratorT>
RealT rand(normal<RealT> const& dist, GeneratorT& rng)
{
std::cout << "In rand(normal,...)" << std::endl;
return RealT(0);
}
template <typename RealT, typename GeneratorT>
RealT rand(exponential<RealT> const& dist, GeneratorT& rng)
{
std::cout << "In rand(exponential,...)" << std::endl;
return RealT(0);
}
} // Namespace lib
namespace my {
/// "my" contains custom wrapper and base classes for dynamic
polymorphism
/// RANDOM NUMBER GENERATORS
template <typename ResultT>
struct base_generator
{
typedef ResultT result_type;
virtual result_type operator()() = 0;
};
template <typename GeneratorT>
struct generator_adaptor: public base_generator<typename
GeneratorT::result_type>
{
typedef GeneratorT generator_type;
typedef typename generator_type::result_type result_type;
generator_adaptor(generator_type const& rng)
: rng_(rng)
{
}
result_type operator()()
{
return rng_();
}
generator_type rng_;
};
template <typename GeneratorT>
base_generator<typename GeneratorT::result_type>* make_generator
(GeneratorT const& rng)
{
return new generator_adaptor<GeneratorT>(rng);
}
/// PROBABILITY DISTRIBUTIONS
// Need to bind GeneratorT at declaration-time in order to create
virtual methods
// This is a *bad* choice since GeneratorT does not belong to the
class state (i.e., there is no
// data member with type GeneratorT)!!
template <typename RealT, typename GeneratorT>
struct base_distribution
{
typedef RealT real_type;
virtual real_type rand(GeneratorT& rng) = 0;
};
template <typename RealT, typename GeneratorT>
RealT rand(base_distribution<RealT, GeneratorT> const& dist,
GeneratorT& rng)
{
std::cout << "In rand(base_distribution,...)" << std::endl;
return dist.rand(rng);
}
// Need to bind GeneratorT at declaration-time in order to create
virtual methods
// This is a *bad* choice since GeneratorT does not belong to the
class state (i.e., there is no
// data member with type GeneratorT)!!
template <typename DistributionT, typename GeneratorT>
struct distribution_adaptor: public base_distribution<typename
DistributionT::real_type,GeneratorT>
{
typedef DistributionT distribution_type;
typedef typename distribution_type::real_type real_type;
distribution_adaptor(distribution_type const& dist)
: dist_(dist)
{
}
distribution_type& distribution()
{
return dist_;
}
distribution_type distribution() const
{
return dist_;
}
real_type rand(GeneratorT& rng)
{
return ::lib::rand<real_type,GeneratorT>(dist_, rng);
}
distribution_type dist_;
};
/// Free polymorphic functions and generators
template <typename DistributionT, typename GeneratorT>
typename DistributionT::real_type rand
(distribution_adaptor<DistributionT,GeneratorT> const& dist,
GeneratorT& rng)
{
std::cout << "In rand(distribution_adaptor,...)" << std::endl;
return rand(dist.distribution(), rng);
}
template <typename DistributionT,typename GeneratorT>
base_distribution<typename DistributionT::real_type,GeneratorT>*
make_distribution(DistributionT const& d)
{
return new distribution_adaptor<DistributionT,GeneratorT>(d);
}
} // Namespace my
int main()
{
typedef double real_type;
typedef lib::minstd generator_type;
typedef my::base_distribution<real_type, generator_type>*
ptr_base_distr_type;
::std::vector<ptr_base_distr_type> distrs;
distrs.push_back
(my::make_distribution<lib::exponential<real_type>, generator_type>
(lib::exponential<real_type>(2.5)));
distrs.push_back(my::make_distribution<lib::normal<real_type>,
generator_type>(lib::normal<real_type>(0, 2)));
generator_type rng(1234);
for (
std::vector<ptr_base_distr_type>::const_iterator it =
distrs.begin();
it != distrs.end();
++it
) {
(*it)->rand(rng);
}
// clean-up
while (!distrs.empty())
{
delete distrs.back();
distrs.pop_back();
}
}
--- [/code] ---
Best Regards,
-- Marco
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]