尊敬的 Stack Exchange 专家,
我正在尝试建立一个类(多变量分布函数),将 boost 分布存储在 std::vector(边际分布函数)中。 虽然这可以使用 boost::variant(参见我的问题:Boost: Store Pointers to Distributions in Vector),但我也尝试了 boost::any。 原因是对于变体,我必须在设置变体时对潜在类型(边际分布)进行硬编码,而我想避免这种情况。
虽然不同的实现分布类不共享一个公共(public)父类,但有一些函数,如 boost::math::cdf 或 boost::math::pdf 可以应用于所有分布,我想在 std::vector 上应用迭代。
使用 any 我生成了下面的代码(运行良好),但现在我遇到了函数 any_cdf 需要检查类型的问题。
虽然我在设置 vector 时绕过了对类型进行硬编码(对于变体),但我现在需要在 any_cdf 函数中对类型进行硬编码(而具有变体的解决方案可以通过模板化访问者函数,因此没有任何类型规范),这意味着需要管理大量代码,大量 if 语句...
但是,逻辑根本没有改变(我强制转换类型,然后在所有 if 语句中应用 cdf 函数),如果存储在 boost 分布之外的其他内容,我不会真正关心函数的行为方式列表。
那么有没有机会吃我的蛋糕并吃掉它,这意味着不被迫在 any_cdf 中硬编码分布的转换类型(很像变体的模板化访问者函数)?
非常感谢你的帮助,H。
附言如果这不可行,在这种情况下我通常会更好地使用 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 的实现在以下位置进行了讨论: visitor pattern for boost::any
最佳答案
Note See my older answer for a discussion of solutions a vector and
boost::any
vs.boost::variant
.
如果您实际上不需要分布的动态 vector - 但只想应用静态已知的分布列表,您可以使用 tuple<>
“逃脱”
现在,借助 Phoenix 和 Fusion 的一些(嗯,很多)魔法,您可以“只”调整 cdf
作为一个懒惰的 Actor :
BOOST_PHOENIX_ADAPT_FUNCTION(double, cdf_, boost::math::cdf, 2)
在这种情况下,一个等效 extended代码示例缩小为:查看 Live On Coliru
int main()
{
typedef boost::tuple<bm::normal, bm::students_t> Dists;
Dists dists(bm::normal(), bm::students_t(1));
double x = 1.96;
boost::fusion::for_each(dists, std::cout << cdf_(arg1, x) << "\n");
std::cout << "\nComposite (multiplication):\t" << boost::fusion::accumulate(dists, 1.0, arg1 * cdf_(arg2, x));
std::cout << "\nComposite (mean):\t\t" << boost::fusion::accumulate(dists, 0.0, arg1 + cdf_(arg2, x)) / boost::tuples::length<Dists>::value;
}
哇哦。那是……不到 6 行代码 :) 最好的部分是它已经完全兼容 c++03。
关于c++ - boost :任意分布的 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22666108/