I am trying to use two different objects of std::uniform_int_distribution
bound (using std::bind
) with the same object std::default_random_engine
as argument (as described here http://www.cplusplus.com/reference/random/), but binding them together results in different behavior than using them unbound:
#include <iostream>
#include <functional>
#include <random>
using namespace std;
int main()
{
default_random_engine generator;
int dist1Max = 10, dist2Max = 10;
uniform_int_distribution<int> dist1(1, dist1Max);
uniform_int_distribution<int> dist2(1, dist2Max);
function<int()> boundDist1 = std::bind(dist1, generator);
function<int()> boundDist2 = std::bind(dist2, generator);
for (int i=0; i<10; ++i)
{
cout << boundDist1() << " " << boundDist2() << endl;
}
cout << endl;
for (int i=0; i<10; ++i)
{
cout << dist1(generator) << " " << dist2(generator) << endl;
}
}
The second loop produces random numbers as I want them, while in the first one boundDist1()
and boundDist2()
always produce the same number in each cycle of the loop.
So my question is:
How does std::bind
change the behavior of the function call and how can I avoid this problem?
The problem is that by default, bind
will copy its argument to the closure, rather than create a reference to them. Random engines being copyable, you get two distinct engines that create the same numbers.
You need to wrap the generators in bind
with std::ref
. This tells bind
that you want to keep a reference to the engine, not make a copy of it.
function<int()> boundDist1 = std::bind(dist1, std::ref(generator));
function<int()> boundDist2 = std::bind(dist2, std::ref(generator));
Here's an ideone run with it.