The following code works fine
#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;
}
However, changing the capture list of the lambda to [=]
or [&, distribution]
or [&, generator]
causes
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'
Are there some kinds of objects can not be captured by value in a lambda ?
Looks like std::normal_distribution<double>::operator()
is not const
.
So you have to add mutable
keyword to your lambda:
std::generate(v.begin(), v.end(), [=] () mutable {
return distribution(generator);
});
std::generate(v.begin(), v.end(), [&, distribution] () mutable {
return distribution(generator);
});
These both work fine.
In general, capture by values requires the object to be copyable. Both std::default_random_generator
and std::normal_distribution
are copyable, so this shouldn't be a problem here.
Lambda captures are always const values or const references. Random number generation is inherently stateful, so the called operator()
cannot be const because it may modify the object state. The error message cryptically reports this by saying that there is no function to call on a const std::normal_distribution<double>
.
If you want to modify the captured objects, you have to declare the lambda as mutable
#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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With