How do I use random_shuffle with a custom random function?

I want use a custom random number generator in VC++11 to randomly shuffle a vector. I have a class called Random, a global instance g_random and a member function g_random.Rand(num) which produces a random non-negative integer no greater than num. Definition of this member looks like this:

std::mt19937::result_type const Random::Rand(std::mt19937::result_type const = std::mt19937::max()){ // content }

So in order to use this function to shuffle my vector I do this:

std::random_shuffle(colony_vector.begin(),colony_vector.end(),&g_random.Rand);

But this gives the following errors:

1>c:\users\main\code\class_world.cpp(54): error C2276: '&' : illegal operation on bound member function expression
1>c:\users\main\code\class_world.cpp(54): error C2780: 'void std::random_shuffle(_RanIt,_RanIt)' : expects 2 arguments - 3 provided


There seems to be 2 issues here; first my referencing of Rand() doesn't seem to be working and for some reason random_shuffle is not expecting 3 input values. Anyone know what I'm doing wrong here? I'm using the latest version of VS 2012.
Last edited on
remove & before your function
Use std::bind() to bind the two parameters to Random::Rand()

1
2
3
4
// object: g_random
// call g_random.Rand(num) with num == 10000
std::random_shuffle( colony_vector.begin(), colony_vector.end(),
                     std::bind( &Random::Rand, g_random, 10000 ) ) ;

MiiNiPaa, your suggestion gives the following error:

1>c:\users\main\code\class_world.cpp(54): error C3867: 'EDIN::Random::Rand': function call missing argument list; use '&EDIN::Random::Rand' to create a pointer to member
1>c:\users\main\code\class_world.cpp(54): error C2780: 'void std::random_shuffle(_RanIt,_RanIt)' : expects 2 arguments - 3 provided
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\algorithm(2243) : see declaration of 'std::random_shuffle'


JLBorges: I'm confused... I thought that the random_shuffle function takes a unary function that takes a single input; how does the std::bind() function you gave achieve this? Sorry about my ignorance here I just don't really understand what's going on...
I'm pretty sure you can't pass a pointer to a particular instance's method like you are trying to. I think you need to use bind() as JLBorges suggests except instead of using 10000 let that be the one parameter passed to the function.

It's been a while since I've tried the syntax, but try:
1
2
3
std::random_shuffle(colony_vector.begin(), colony_vector.end(),
                    std::bind(&Random::Rand, g_random, _1));
// the bind() call "creates" a one-argument function that essentially calls g_random.Rand(_1) where _1 is the argument 
> I thought that the random_shuffle function takes a unary function

Yes, that is one overload.
There is also an overload that takes a uniform random number generator; overload (3) here: http://en.cppreference.com/w/cpp/algorithm/random_shuffle

1
2
3
4
5
6
// overload 3
std::random_shuffle( colony_vector.begin(), colony_vector.end(),
                     std::bind( &Random::Rand, g_random, 10000 ) ) ;
// overload 2
std::random_shuffle( colony_vector.begin(), colony_vector.end(),
                     std::bind( &Random::Rand, g_random, std::placeholders::_1 ) ) ;

Ah right that all makes sense; I need to make the method unary by providing the "invisible" this pointer. So here's my solution as suggested:

std::random_shuffle(colony_vector.begin(),colony_vector.end(),std::bind(&Random::Rand, g_random,std::placeholders::_1));

Thanks
Topic archived. No new replies allowed.