无法在lambda中按值捕获随机分布和生成器?

时间:2017-08-28 06:37:05

标签: c++ c++11 lambda

以下代码可以正常使用

#include <iostream>
#include <random>

int main() {
    std::default_random_engine generator;
    std::normal_distribution<double> distribution(5.0, 2.0);
    std::vector<double> v(100);

    std::generate(v.begin(), v.end(), [&] () { return distribution(generator); });

    return 0;
}

但是,将lambda的捕获列表更改为[=][&, distribution][&, generator]会导致

rand.cpp:9:59: error: no matching function for call to object of type 'const std::normal_distribution<double>'
error: assigning to 'double' from incompatible type 'void'

在lambda中是否有某些类型的对象无法通过值捕获?

2 个答案:

答案 0 :(得分:4)

看起来std::normal_distribution<double>::operator()不是const。 所以你必须在lambda中添加mutable关键字:

std::generate(v.begin(), v.end(), [=] () mutable { 
   return distribution(generator); 
});

std::generate(v.begin(), v.end(), [&, distribution] () mutable { 
   return distribution(generator); 
});

这两种方法都很好。

答案 1 :(得分:4)

通常,按值捕获需要对象可复制。 std::default_random_generatorstd::normal_distribution都是可复制的,因此这不应该是一个问题。

Lambda captures are always const values or const references.随机数生成本质上是有状态的,因此被调用的operator()不能是const,因为它可能会修改对象状态。错误消息通过声明在const std::normal_distribution<double>上没有调用函数来加密地报告这一点。

如果要修改捕获的对象,则必须将lambda声明为可变

#include <iostream>
#include <random>
#include <algorithm>

int main() {
    std::default_random_engine generator;
    std::normal_distribution<double> distribution(5.0, 2.0);
    std::vector<double> v(100);

    std::generate(v.begin(), v.end(), [generator, distribution] () mutable { return distribution(generator); });

    return 0;
}