C++11 class seed_seq random header

The C++11 class seed_seq generate sequences of seeds for random number generators.To know exactly how to use this class please know the uses of the member functions clearly especially the ‘generate’ member function.The class declaration and it’s data members and functions are given below.

Link :C++11 random number generator

class seed_seq

Data member

typedef uint_least32_t result_type; //this is public type

vector<result_type> v; //This is private type

The ‘uint_least32_t‘ is a ‘typedef’ of unsigned int type.

Constructors

There are three constructors.

seed_seq( );

template<class T>
seed_seq(initializer_list<T> il); //T is unsigned int type

template<class InputIterator>
seed_seq(InputIterator begin , InputIterator end); //InputIterator is an input iterator type

Member functions

template<class RandomAccessIterator>
void generate(RandomAccessIterator begin , RandomAccessIterator end);

size_t size( ) const ;

template<class OutputIterator>
void param(OutputIterator dest) const; 

seed_seq(const seed_seq& ) = delete; 

void operator=(const seed_seq& ) = delete; 

A detail description of each of these functions is given below.


template<class RandomAccessIterator>
void generate(RandomAccessIterator begin , RandomAccessIterator end);

The C++11 class seed_seq ‘generate’ member function purpose is to generate a sequence of random numbers that can be used as a seed for the engine.

Parameters:
begin -It points to the starting point of the storage.

end -It points to the last storage.

Return type
void

If ‘begin==end‘ nothing is done.Else the random sequence generated by the function is stored in the storage starting from the position pointed by the ‘begin’ iterator.

int main( )
{
vector<int> vec={ 0 , 0 , 0};
seed_seq seeds ;  //default constructor is called
seeds.generate( vec.begin( ) , vec.end( ) );  //stores 3 random number in the ‘vec’ storage

for(auto elem:vec )
{
cout<< elem << ” ” ;
}

cout<< “\n\n” ;

default_random_engine dre1( vec[0] ) , dre2( vec[1] ) ;  //vec[0] and vec[1] is passed as seed value

cin.get( );
return 0;
}

Output in Code::Blocks ,

572005652
-95471962
-526826058
 
1562189192 1720536236

The ‘generate’ stores the random numbers in the ‘vec’ storage and the vec[0] and vec[1] is passed as the seed thus changing the state of the dre1 and dre2 engine,this in turn render a different random number.The above code has no flaw as far as how the ‘generate’ function is used is concerned.

However,there is another way to make the ‘generate’ function generate a different random numbers-completely different from the above output.In this method we pass the iterator pointing to beginning and end of the vector storage as an argument to the constructor during the seed_seq object creation.It seems in this method the ‘generate’ function algorithm utilizes the values initialized to the vector to render a random sequence;I am not discussing here the algorithm implemented by the function.Consider the code below.

 int main( )
{
vector<int> vec={ 0 , 0 , 0};
seed_seq seeds( vec.begin( ) , vec.end( ) ) ;  //Calls third constructor 
seeds.generate( vec.begin( ) , vec.end( ) );  //stores 3 random number in the ‘vec’

for(auto elem:vec )
{
cout<< elem << ” ” ;
}

cout<< “\n\n” ;

default_random_engine dre1( vec[0] ) , dre2( vec[1] ) ;  //vec[0] and vec[1] is passed as seed value

cin.get( );
return 0;
}

Output in Code::Blocks ,

-17368449
997445878
-659774253
 
146287263 815523064

You can see the output is completely different from the previous program.By either passing an argument during ‘seed_seq’ object creation or by not passing any argument we can obtain two different random sequences.



template<class OutputIterator>
void param(OutputIterator dest) const;

The C++11 class seed_seq ‘param’ function copies a sequence of 32-bit unit to the given destination.This function simply re-copies the initial content of the vector or array storage to the storage if any changes is made to the storage by calling the ‘generate’ function.

Parameters:
dest -The iterator pointing to the storage where the the content of the storage is to be copied.

Return type
void

Note this function makes sense only if the second and third version constructor of the seed_seq class is called.If the default constructor is called this function will copy some garbage value or in worst case scenario your program might break.

 int main( )
{
int arr[5]={ 10 , 20 , 30 ,40 , 50} ;

seed_seq seeds( &arr[0] , &arr[5] );

//Calling ‘generate’ function
seeds.generate( &arr[0] , &arr[5] );

//print out 'arr' content
for(auto elem:arr )
{
cout<< elem << “\n” ;
}

cout<< “\n\n” ;

//calling ‘param’ function
seeds.param( &arr[0] );

for(auto elem:arr )
{
cout<< elem << ” “;
}

cin.get( );
return 0;
}

Output in Code::blocks,

221105115
-470493240
1310772813
769809557
-1428398116
 
10 20 30 40 50

In the code after ‘generate’ function is called the content of the ‘arr’ array has changed.But you can see that calling the ‘param’ function re-copies the initial values (the values before generate was called) of the ‘arr’ to the array.


size_t size( ) const ;

This function returns the number of elements between the iterator pointed by the first and second arguments passed to the seed_seq object’s constructor.

If initializer_list type is passed as argument,the number of elements hold by the initializer_list is returned.

If the default constructor is called or no iterators is passed during the constructor call the ‘size’ function always return 0.

 int main( )
{
vector<double> vd={ 9.89 , 00.63 , 8.21 };
seed_seq seeds , seedsv( vd.begin( ) , vd.end() ) ;

cout<< seedsv.size( ) << endl
seeds.size( ) ;

cin.get( );
return 0;
}

Output,

3
0

The ‘seeds’ object has no argument pass so default constructor is called and the size is 0,but in seedsv the size is 3 since the vd.begin( ) and vd.end() are passed as argument.


Copy constructor and operator=

Since the copy constructor and the operator= are defined as ‘=delete‘ they cannot be called.Defining a function as ‘=delete’ prohibit the call to that function.

 int arr[2]={0};
seed_seq seeds( &arr[0] , &arr[2]) ;

seed_seq seeds1(seeds) ; //error!

seeds_seq seeds2 ;

seeds2=seeds ; //error!

More about ‘=delete’ keyword is discuss in another post.