1

stl c++11 solution :

auto distribution = std::bind(std::normal_distribution<double>{mean, stddev},
                              std::mt19937(std::random_device{}())
                              );
std::transform(data.begin(), data.end(), data.begin(),
               std::bind(std::plus<double>(), std::placeholders::_1, distribution()));

Easy range-based loop :

for (auto& d : data) {
  d += distribution();
}

My STL solution doesn't work as it always take the first number it generated from the distribution. I tried with the placeholder as the 3rd parameter but it doesn't change anything. All of my data is incremented by the same number which is not something I want. I want the same behaviour as the range-based loop.

It this something possible?

1 Answers1

2

Let's rewrite your second bind as lambda, to get a feeling how it actually works:

auto func = std::bind(std::plus<double>(), std::placeholders::_1, distribution())

is equivalent too

auto d = distribution();

auto func = [d](double x){ return std::plus<double>()(x,d); };

or, if we use C++14's initialization feature:

auto func = [d=distribution()](double x){ return std::plus<double>()(x,d); };

As you can see, distribution() gets called only once. However, you don't want to use the return value of distribution, you want to call distribution for every call of func. While it's possible to do that with bind, a lambda will make this a lot easier:

std::transform(data.begin(), data.end(), data.begin(),
               [&distribution](double x){ return x + distribution(); });

And in my opinion, that's a lot easier to read than your previous bind. Note that std::bind (or rather boost::bind) predates lambdas. There were some issues with lambdas in C++11 compared to std::bind, but with C++14, lambdas are usually a lot easier to handle, read and understand without sacrificing much.

Zeta
  • 103,620
  • 13
  • 194
  • 236