C++ - How to correctly bind a default_random_engine to two different uniform_int_distributions

StackOverflow https://stackoverflow.com/questions/23449243

  •  14-07-2023
  •  | 
  •  

Pregunta

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?

¿Fue útil?

Solución

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top