jeudi 21 mars 2019

Unpack vector into arguments to call functions that have a variable number of arguments

It's a little bit tricky trying to phrase this question.

So let's say I have a large number of functions that all have varying numbers of arguments - some have none, some have one, some have a few or many more. I receive the parameters for these functions in a vector. Normally, I can just call them like this:

 #include <vector>

 int my_functionA(std::string a) { /*...*/ return 1; }     
 int my_functionB(std::string a, std::string b) { /*...*/ return 2; }  

 void some_useful_function(std::vector<std::string> vec, int choice) {
      if (choice == 1) {
           // Error checking would happen here
           int val = my_functionA(vec[0]);
           // Do something with val
           // ...
      }
      else if (choice == 2) {
           // Error checking would happen here
           int val = my_functionB(vec[0], vec[1]);
           // Do something with val
           // ...
      }
 }

Error checking would be making sure there are the correct number of arguments, etc. But this gets very tedious if I have a large number of functions, and the error checks and what I do with the return value are the same. I end up repeating the same ~15 lines of code 100 times, and if I ever decide I want to change or add something to that 15 line 'sequence', I'd have to redo it a hundred times.

It would make more sense if I could make a map from a choice to a data structure that has the function pointer and other information I'll need, and then the my_useful_function would be more like:

 struct funcPointer {
      funcPointer(void * f, int n) : fnc(f), numOfArgs(n) {};
      void * fnc;
      int numOfArgs;
 };

 std::map<int, funcPointer> = { 
      {1, funcPointer(my_functionA, 1)},
      {2, funcPointer(my_functionB, 1)}};

 void some_useful_function(std::vector<std::string> vec, int choice) {
      if (map.count[choice] > 0) {
           // Do stuff if map[choice].numOfArgs is insufficient
           int val = map[choice].fnc(vectorSomehowConvertedToArguments);
           // Do stuff with the return value
      }
 }

This answer with the 'index trick' got me really close, but since it requires a constant for the unpack_caller, I'm not sure how to mesh that into my map / data struct.

Aucun commentaire:

Enregistrer un commentaire