3

I am currently making a class for which I'd like one of the private members to be initialised with a random number each time the object is created. The following code causes no problem:

private:
    unsigned random = rand() % 10;

I would, however, like to use the C++11 random engines and distributions to do this. I would like to be able to do something along the lines of the following code, which will not compile but will give a general idea of what I'm trying to do:

private:
unsigned random = distribution(mersenne_generator(seed));

static std::random_device seed_generator;
static unsigned seed = seed_generator(); //So that it's not a new seed each time.
static std::mt19937 mersenne_generator;
static std::uniform_int_distribution<unsigned> distribution(0, 10);

This code won't compile because I'm trying to define some of the static members in the class. I'm not sure where to define them, however. I could create a member function that initialises everything, but then I would have to run it in main, which I don't want to. I would like to just sort out all the random definitions in class so that when I create an object in main, it will create the random number implicitly. Any suggestions?

Praetorian
  • 106,671
  • 19
  • 240
  • 328
JamesLens
  • 447
  • 6
  • 14
  • This might help http://stackoverflow.com/questions/11498304/generate-random-numbers-in-c-at-compile-time – imreal Mar 18 '14 at 19:43
  • Is this question just how to define/initialize static data members? Could you post a [SSCCE](http://sscce.org)? – dyp Mar 18 '14 at 19:52
  • I'm trying to implement the same functionality as the first block of code (which generates a random number for that member each time an object is created) using C++11 random generators and engines. I have no idea how to do so, the static data members are just my attempt, but it doesn't compile. I included it as a sort of pseudocode to show my intention. – JamesLens Mar 18 '14 at 19:56

1 Answers1

8

You need to define the static data members outside the class definition. For instance, this will work:

struct foo
{
private:
    unsigned random = distribution(mersenne_generator);    
    static std::random_device seed_generator;
    static unsigned seed;
    static std::mt19937 mersenne_generator;
    static std::uniform_int_distribution<unsigned> distribution;
};

std::random_device foo::seed_generator;
unsigned foo::seed = seed_generator();
std::uniform_int_distribution<unsigned> foo::distribution(0, 10);
std::mt19937 foo::mersenne_generator(foo::seed);

The definitions for the static data members should be placed in a .cpp file, else you run the risk of violating the one definition rule.

Live example

Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • 1
    TIL: name lookup in *brace-or-equal*-initializers for NSDM is the same as name lookup inside member function definitions (it's postponed until the end of the class definition). – dyp Mar 18 '14 at 19:58
  • 4
    I would encapsulate the static data members into a static member function so as to avoid the requirement for separate out-of-class definitions, [like so.](http://coliru.stacked-crooked.com/a/64c9a61056da2e03) Make the linker do the work ;) – Casey Mar 18 '14 at 20:04
  • Awesome, that did work. Thanks a lot, static members always confuse me with definitions vs declarations. Edit: Thanks Casey, that is some sexy code. – JamesLens Mar 18 '14 at 20:04