尊敬的 Stack Exchange 专家,
我正在尝试建立一个类(多变量分布函数),它将升压分布存储在 std::vector (边际分布函数)中。虽然这可以使用 boost::variant (请参阅我的问题:Boost: Store Pointers to Distributions in Vector),但我也尝试了 boost::any。原因是使用变体时,我必须在设置变体时对潜在类型(边际分布)进行硬编码,而我想避免这种情况。
虽然不同实现的分布类不共享一个共同的父类,但有一些函数,如 boost::math::cdf 或 boost::math::pdf 可以应用于所有分布,并且我想应用迭代标准::向量。
使用我生成的任何以下代码(运行良好),但现在我遇到了函数 any_cdf 需要检查类型的问题。
虽然我在设置向量时规避了对类型的硬编码(至于变体),但我现在需要对 any_cdf 函数中的类型进行硬编码(而具有变体的解决方案可以通过模板化的访问者函数处理 cdf 函数的应用,因此没有任何类型规范),这意味着要管理大量代码,大量 if 语句......
但是,逻辑根本没有改变(我转换了类型,然后在所有 if 语句中应用了 cdf 函数),如果除了 boost 分布之外的其他内容存储在列表中,我也不会真正关心函数的行为。
那么有没有机会得到我的蛋糕并吃掉它,这意味着不会被迫在 any_cdf 中硬编码发行版的铸造类型(很像变体的模板化访问者函数)?
非常感谢您的帮助,H.
Ps 如果这不可行,在这种情况下,我通常会更好地使用 boost::any 或 boost::variant 吗?
#include <boost/math/distributions.hpp>
#include <boost/any.hpp>
#include <vector>
#include <iostream>
#include <limits>
//template function to apply cdf
template<class T> T any_cdf(boost::any a, T &x){
//declare return value
T y;
//cast any with hardcoded types
if (a.type() == typeid(boost::math::normal_distribution<T>)){
y = boost::math::cdf(boost::any_cast< boost::math::normal_distribution<T> >(a),x);
} else if (a.type() == typeid(boost::math::students_t_distribution<T>)){
y = boost::math::cdf(boost::any_cast< boost::math::students_t_distribution<T> >(a), x);
} else {
//return NaN in case of failure or do something else (throw exception...)
y = std::numeric_limits<T>::quiet_NaN();
}
return(y);
}
int main (int, char*[])
{
//get distribution objects
boost::math::normal_distribution<double> s;
boost::math::students_t_distribution<double> t(1);
//use any to put just any kind of objects in one vector
std::vector<boost::any> vec_any;
vec_any.push_back(s);
vec_any.push_back(t);
//evaluation point and return value
double y;
double x = 1.96;
for (std::vector<boost::any>::const_iterator iter = vec_any.begin(); iter != vec_any.end(); ++iter){
y = any_cdf<double>(*iter,x);
std::cout << y << std::endl;
}
return 0;
}
编辑:关于评论,任何似乎都不是手头任务的最简单/最佳选择。然而,出于完整性原因,类似 boost::any 的实现的访问者在以下位置讨论: boost::any 的访问者模式