1

I have a way to shuffle my std::vector. Specifically, I do it using C++98 approach:

void LoopGenerator::shuffle()
{
    std::random_shuffle(stripes.begin(), stripes.end(), seed);
}

Where LoopGenerator is a class that throws out some data in random order. The vector stripes is defined this way:

std::vector<Generator*> stripes;

Generator is a virtual superclass of LoopGenerator. The vector is supposed to allow all kinds of random generators to be contained and nested, which I use for generating stripes. For example, generate 5-50 thin green stripes and then thick brown stripe:

random stripes forest theme

The problem is that my shuffle throws an error:

1>  LoopGenerator.cpp
1>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\algorithm(2181): error C2064: term does not evaluate to a function taking 1 arguments
1>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\algorithm(2206) : see reference to function template instantiation 'void std::_Random_shuffle<random_stripes::Generator**,int,__w64 int>(_RanIt,_RanIt,_Fn1 &,_Diff *)' being compiled
1>          with
1>          [
1>              _RanIt=random_stripes::Generator **,
1>              _Fn1=int,
1>              _Diff=__w64 int
1>          ]
1>          LoopGenerator.cpp(79) : see reference to function template instantiation 'void std::random_shuffle<std::_Vector_iterator<_Myvec>,int&>(_RanIt,_RanIt,_Fn1)' being compiled
1>          with
1>          [
1>              _Myvec=std::_Vector_val<std::_Simple_types<random_stripes::Generator *>>,
1>              _RanIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<random_stripes::Generator *>>>,
1>              _Fn1=int &
1>          ]

This points me to line 2181 in <algorighm>. I can see nothing I could understand there.

So what's wrong? Is there a problem with shuffling array of pointers? Or is there something wrong with them being abstract class pointers?

More code:

Generator.h - topmost class that is in std::vector<Generator*> stripes

namespace random_stripes {

    class Generator
    {
    public:
        Generator(int);
        Generator();
        virtual ~Generator() {};
        //Returns next stripe and moves internal iterator
        virtual RandomStripe next() = 0;
        //Fills the variables with data AND ITERATES THE POINTER if third argument is true
        virtual void getData(std::string&, int&, bool=true) = 0;
        //Informs parent class/procedure whether all stripes were returned
        virtual bool end() = 0;
        //Reset the pointer (and anything else)
        virtual void reset() = 0;
        //Get/set the random seed
        virtual int setSeed(int);
        virtual int getSeed();
    protected:
        int seed;
    };
}

LoopGenerator.h

namespace random_stripes {
    class LoopGenerator : public ManyStripes
    {
    public:
        LoopGenerator();
        //True if shuffled
        LoopGenerator(bool);
        ~LoopGenerator();
        //If true, every LAP is shuffled (otherwise order is constant)
        bool shuffled;
        //OVERRIDEN METHODS
        virtual RandomStripe next();
        virtual void reset();
        virtual bool end();
        virtual void getData(std::string&, int&, bool=true);
        //Properties
        unsigned int repeat;  //How many times should this sequence repeat
    protected:
        virtual int iterate();
        unsigned int lap;  //How many times DID this sequence repeat aready

        void shuffle();    //Shuffle list of elements (defined in ManyStripes)

        //Reset without forgeting lap
        void makeLap();
    };
}
Community
  • 1
  • 1
Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778

1 Answers1

1

That's because you're calling random_shuffle incorrectly:

std::random_shuffle(stripes.begin(), stripes.end(), seed);

It doesn't take a seed, it takes a function:

template< class RandomIt, class RandomFunc >
void random_shuffle( RandomIt first, RandomIt last, RandomFunc& r );

Where the RandomFunc is a function that, when called with n should return a random number in the range [0,n). It's an implementation of the Knuth Shuffle. You probably meant to call:

srand(seed);
std::random_shuffle(stripes.begin(), stripes.end()); // typically uses rand()

Or, with C++11:

std::shuffle(stripes.begin(), stripes.end(), std::mt19937{seed});
Barry
  • 286,269
  • 29
  • 621
  • 977