Good practice choosing an algorithm randomly with C ++

Setup:
It is necessary to create a pseudo-random structure. There are several methods / algorithms available for creating other content. All algorithms will generate a list of characters (but maybe something else) ... the important part is that they all return the same type of values โ€‹โ€‹and need the same type of input arguments.

It should be possible to call the GetRandomPattern () method, which will use a random one of the algorithms each time it is called.

My first approach was to put each algorithm in its own function and select a random one each time GetRandompattern () is called. But I did not come up with a different way of choosing between them, and not with the expression of the switch statement, which is uncomfortable, ugly and inflexible.

class PatternGenerator{ public: list<char> GetRandomPattern(); private: list<char>GeneratePatternA(foo bar); list<char>GeneratePatternB(foo bar); ........ list<char>GeneratePatternX(foo bar); } 

What would be a good way to select a random GeneratePattern function each time the GetRandomPattern () method is called?

Or should the whole class be designed differently?

Thank you so much

+6
c ++ design-patterns random function-pointers
source share
4 answers

Thank you for all your input. I decided to go with function pointers, mainly because I did not know them before, and they seem very powerful, and it was a good chance to get to know them, but also because it saves me a lot of lines of code.

If I used Ruby / Java / C #, I would decide to use a development strategy template; -)

 class PatternGenerator{ typedef list<char>(PatternGenerator::*createPatternFunctionPtr); public: PatternGenerator(){ Initialize(); } GetRandomPattern(){ int randomMethod = (rand()%functionPointerVector.size()); createPatternFunctionPtr randomFunction = functionPointerVector.at( randomMethod ); list<char> pattern = (this->*randomFunction)(); return pattern; } private: void Initialize(){ createPatternFunctionPtr methodA = &PatternGenerator::GeneratePatternA; createPatternFunctionPtr methodB = &PatternGenerator::GeneratePatternB; ... functionPointerVector.push_back( methodA ); functionPointerVector.push_back( methodB ); } list<char>GeneratePatternA(){ ...} list<char>GeneratePatternB(){ ...} vector< createPattern > functionPointerVector; 

The readability is not much worse, as it would be with the Design Pattern Solution, it is easy to add new algorithms, pointer arithmetic would be encapsulated inside the class, it prevents memory leaks, and it is very fast and efficient ...

+1
source share

Create one class for each algorithm, each of which subclasses the generator class. Put instances of these objects on the list. Choose one random case and use it!

More generally, if you start to create several alternative methods with the same signature, something screaming โ€œputs us in the native classesโ€ of you :)

Update I can not resist the arguments a bit more for an object-oriented solution after a pointer sentence has appeared

  • Imagine that at some point you want to print which method created some random thing. With objects easy, just add a "name" method or something else. How do you want to achieve this if you have a pointer? (yes, create a dictionary from pointers to strings, hm ...)
  • Imagine that you learned that you have ten methods, five of which differ only in parameter. So, you write five functions โ€œjust to clear OOP garbage codeโ€? Or do you rather have a function that happens to be able to store some state with it (also known as an object?)
  • I am trying to say that this is a textbook application for some OOP projects. The above points just try to spell it out a bit and argue that even if it works with pointers, this is not a reliable solution. And you should not be afraid to create code that speaks to the reader (i.e. your future, in four weeks or so), telling this person what he is doing.
+9
source share

You can create an array of function pointers. This avoids creating a whole series of different classes, although you still have to assign pointers to array functions. In any case, you will make many repeated lines. In your example, this is the GetRandomPattern method. In mine, this is in the PatternGenerator constructor.

 #define FUNCTION_COUNT 24 typedef list<char>(*generatorFunc)(foo); class PatternGenerator{ public: PatternGenerator() { functions[0] = &GeneratePatternA; functions[1] = &GeneratePatternB; ... functions[24] = &GeneratePatternX; } list<char> GetRandomPattern() { foo bar = value; int funcToUse = rand()%FUNCTION_COUNT; functions[funcToUse](bar); } private: generatorFunc functions[FUNCTION_COUNT]; } 
+5
source share

One way to avoid coding using switches is to use a development strategy template. As an example:

  class IRandomPatternGenerator
 {
 public:
   virtual list <int> makePattern (foo bar);
 };

 class ARandomPatternGenerator: public IRandomPatternGenerator
 {
 public:
   virtual list <int> makePattern (foo bar)
   {
     ...    
   }
 };

 class BRandomPatternGenerator: public IRandomPatternGenerator
 {
 public:
   virtual list <int> makePattern (foo bar)
   {
     ...    
   }
 };

Then you can select a specific algorithm depending on the type of runtime of your instance of RandomPatternGenerator. (As an example of creating a list, for example nicolas78)

+1
source share

All Articles