Hi Stack Exchange Experts,
I'm trying to collect pointers to different statistical distributions provided by Boost in one vector. If distributions would be derived from one (virtual) parent class I could write something like
std::vector<Parent> v;
boost::math::normal_distribution<double> n;
boost::math::students_t_distribution<float> t(4);
boost::math::normal_distribution<double> *p1 = new boost::math::normal_distribution<double>(n);
boost::math::students_t_distribution<float> *p2 = new boost::math::students_t_distribution<float>(t);
v.push_back(p1);
v.push_back(p2);
and then iterate over the vector and apply functions etc. to the dereferenced pointers. But since this is not the case I don't really know how to store the pointers in one place?
So my question is, if there is a way to store pointers to different template classes in one variable/list/vector... (that can be handled conveniently like std::vector for example).
Remark that for example the Boost pdf density function can be applied to the dereferenced pointers regardless of the specific type (so storing them in one vector makes sense in some cases).
//////////////////////////////////////////////////////////////////////////
I played around with the different (nice) answers and finally decided to stick to boost::variant in conjunction with boost::static_visitor. Below is a full application that does what I outlined in my original question:
#include <boost/math/distributions.hpp>
#include <boost/variant.hpp>
#include <vector>
#include <iostream>
//template based visitor to invoke the cdf function on the distribution
class cdf_visitor_generic : public boost::static_visitor<double>
{
public:
//constructor to handle input arguments
cdf_visitor_generic(const double &x) : _x(x) {}
template <typename T>
double operator()(T &operand) const {
return(boost::math::cdf(operand,_x));
}
private:
double _x;
};
//shorten typing
typedef boost::variant< boost::math::normal_distribution<double>, boost::math::students_t_distribution<double> > Distribution;
int main (int, char*[])
{
//example distributions
boost::math::normal_distribution<double> s;
boost::math::students_t_distribution<double> t(1);
//build a variant
Distribution v = t;
//example value for evaluation
double x = 1.96;
//evaluation at one point
double y = boost::apply_visitor( cdf_visitor_generic(x),v);
std::cout << y << std::endl;
//build a vector and apply to all elements of it:
std::vector<Distribution> vec_v;
vec_v.push_back(s);
vec_v.push_back(t);
for (std::vector<Distribution>::const_iterator iter = vec_v.begin(); iter != vec_v.end(); ++iter){
//apply cdf to dereferenced iterator
double test = boost::apply_visitor( cdf_visitor_generic(x), *iter);
std::cout << test << std::endl;
}
return 0;
}
The only drawback I see is that the type of distribution needs to be explicitly specified (in the variant) so it could be that boost::any adds more freedom.
Thank you for the great help!
Hank