Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use std::uniform_int_distribution and define its range later

Tags:

c++

random

c++11

I have problem where I want to create a std::uniform_int_distribution in a struct and then give its range later. Below is what I want.

#include <random>
#include <iostream>

std::random_device rd;
std::mt19937 gen(rd());

struct group_s {
   int k;
   std::uniform_int_distribution<> dis;
} group;


int main()
{  
    group.dis(0,19);
    std::cout << group.dis(gen) << ' ';
}

I am getting the following error:

no match for call to '(std::uniform_int_distribution<>) (int, int)'
  cpu_group.dis(0,19);

How do I do this?

like image 708
eswaat Avatar asked Feb 11 '23 00:02

eswaat


2 Answers

Use param():

using param_t = std::uniform_int_distribution<>::param_type;

group.dis.param(param_t(0, 19));

If the parameters change every time you use the distribution, then you can also consider using the two-parameter overload of operator() instead:

std::cout << group.dis(gen, param_t(0, 19)) << ' ';

As distribution objects are allowed to store extra bits of entropy obtained during a previous operator() call, this approach can be more efficient than constructing a new distribution object and assigning it.

Note that the cppreference page is incomplete and doesn't document the requirements the standard imposes on param_type. Given a distribution type D and its associated param_type P,

For each of the constructors of D taking arguments corresponding to parameters of the distribution, P shall have a corresponding constructor subject to the same requirements and taking arguments identical in number, type, and default values. Moreover, for each of the member functions of D that return values corresponding to parameters of the distribution, P shall have a corresponding member function with the identical name, type, and semantics.

(§26.5.1.6 [rand.req.dist]/p9)

like image 102
T.C. Avatar answered Feb 13 '23 14:02

T.C.


You can just do

group.dis = std::uniform_int_distribution<>(0,19);

or

group.dis.param(std::uniform_int_distribution<>::param_type(0,19));

Another way would be to add a method to your struct

struct group_s {
    int k;
    std::uniform_int_distribution<> dis;
    void set(int a, int b) { dis = std::uniform_int_distribution<>(a,b); }
} group;


group.set(0,19);
like image 24
Amxx Avatar answered Feb 13 '23 14:02

Amxx