在VS2013中初始化std :: discrete_distribution

时间:2014-02-22 19:33:01

标签: c++ c++11 visual-studio-2013 std c++-standard-library

我有一个std::vector<float> weights;包含权重列表。在运行该程序的某个阶段之前,我不知道该列表中的内容。我想做

std::discrete_distribution<> dist(weights.begin(),weights.end());

但VS2013似乎没有std :: discrete_distribution的构造函数,它接受迭代器范围。有没有解决方法?

2 个答案:

答案 0 :(得分:10)

比较cppreference.comstd::discrete_distribution的{​​{3}}:

这些是VS2013提供的构造函数:

discrete_distribution();
explicit discrete_distribution(
    const param_type& par0
);
discrete_distribution(
    initializer_list<double> IList
);
template<class Fn>
    discrete_distribution(
        size_t count,
        double low, 
        double high, 
        Fn func
);

缺少一个重要的构造函数,可能是因为Microsoft开发人员没有时间实现它:

template< class InputIt >
 discrete_distribution( InputIt first, InputIt last );

这意味着,除非文档不完整,否则您根本无法为此类使用基于迭代器的构造函数。切换到另一个编译器(如clang或g ++),或等到实现此功能。

现在可以使用解决方法:

std::size_t i(0);
assert( !weights.empty() ); // No weights would be very weird.
std::discrete_distribution<> dist(weights.size(),
                                  0.0, // dummy!
                                  0.0, // dummy!
                                  [&weights,&i](double)
{
   auto w = weights[i];
   ++i;
   return w;
 });

我希望至少支持lambdas ;-)重要的是通过引用捕获i,以便它正确递增。演示:Microsoft reference

为什么这样做?我们在这里使用的构造函数是:

template< class UnaryOperation >
discrete_distribution( std::size_t count, double xmin, double xmax,
                       UnaryOperation unary_op );

http://ideone.com/nIBUts告诉我们count(在我们的案例中为weights.size()),以及xminxmax用于创建权重使用UnaryOperation

我们有意无视忽略 xminxmax。作为UnaryOperation,我们使用lambda

[&weights,&i](double)
{
   auto w = weights[i];
   ++i;
   return w;
 }

[&weights,&i](double)
{
   return weights[i++];
}

如果您愿意。

现在,我们忽略该运算符的输入值,只返回向量的第i个元素。我们通过引用捕获向量和索引以避免复制。

答案 1 :(得分:0)

std::discrete_distribution<> dist(
    weights.size(), 
    -0.5, 
    -0.5+weights.size(), 
    [&weights](size_t i) 
    { 
        return weights[i]; 
    });

或就迭代器而言:

//replacement code for: std::discrete_distribution<> dist(first, last);
auto first = weights.cbegin();
auto last = weights.cend();
auto count = std::distance(first, last);
std::discrete_distribution<> dist(
    count, 
    -0.5, 
    -0.5+count, 
    [&first](size_t i) 
    { 
        return *std::next(first,i); 
    });

这避免了必须捕获可变i变量。传递给lambda的参数可以用作索引。