Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling the appropriate function based on an enumeration, but using templates

Tags:

c++

templates

I have this wrapper function that is supposed to call the appropriate function on a large dataset based on the type of data it contains, like this:

void WrapperFunc( int iRealDataType, int iUseAsDataType )
{
    // now call the right function based on both arguments
    switch ( iRealDataType )
    {
          case FancyType1:
          switch ( iUseAsDataType )
          {
               case CoolType1: DataAnalysisFunc_Fancy1_Cool1(); break;
               // etc.
          }
          // etc.
    }
}

So far, this was solved by having two nested switch statements and then calling one of the many many specialized functions for each existing combination of Real and UseAs data type. However as the number of defined types grows it is a nightmare to maintan the code base. So I decided to finally use templates. I mostly avoid them if I can, but this time they suit the problem well.

So now instead of DataAnalysisFunc_Fancy1_Cool1 i would like to call DataAnalysisFunc<FancyType1,CoolType1> ang get rid of the hundreds of lines of switch statements, BUT i cannot use it like this, since FancyType1 is an enum, not the type (which is Fancy1 for example).

Just to clarify - I know this sounds like a stupid artificial example, but I tried to simplify the problem as much as possible to get to the core of it, instead of explaining the ton of details that would go into a much more concrete example.

EDIT: my data analysis functions are in reality CUDA kernels - this will probably rule out some possible solutions. Sorry for that.

like image 754
PeterK Avatar asked Mar 21 '23 06:03

PeterK


2 Answers

Templates sound like the wrong solution. What you want is a lookup table.

typedef void (*DataAnalysisFunc)();
const DataAnalysisFunc DataAnalysisFunctions[NumFancyTypes][NumCoolTypes] = {
  /*Fancy1*/ {
    /*Cool1*/ &DataAnalysisFunc_Fancy1_Cool1,
    /*Cool2*/ &DataAnalysisFunc_Fancy1_Cool2 }
  /*Fancy2*/ {
    /*Cool1*/ &DataAnalysisFunc_ImpossibleCombination, // can't happen, throw or something
    /*Cool2*/ &DataAnalysisFunc_Fancy2_Cool2 }
};

void WrapperFunc(int realDataType, int useAsDataType) {
  assert(realDataType >= 0 && realDataType < NumFancyTypes);
  assert(useAsDataType >= 0 && useAsDataType < NumCoolTypes);
  (*DataAnalysisFunctions[realDataType][useAsDataType])();
}

Now, if those DataAnalysisFuncs share a lot of code, templates might help you there, but not for dynamic dispatch.

like image 155
Sebastian Redl Avatar answered Apr 08 '23 04:04

Sebastian Redl


BUT i cannot use it like this, since FancyType1 is an enum, not the type (which is Fancy1 for example)

You can convert enum to type, just use one of metaprogramming basic tools:
Int2Type, it is used to replace run-time branches of if statements on the compile time dispatches. It looks like:

template <int Number>
struct Int2Type
{
  enum {value};
};

Int2Type - is treated as a type, using it and function overloading - you can replace if statements.

UPDATE: I added some example here, to make my answer more clear

1. Int2Type
  // usage allows to implement dispatch in a compile time instead of branching statements in a run-time
  template <int Val>
  struct Int2Type
  {
    static const int val_= Val;
  };

  template <typename ItBegin, typename ItEnd>
  void doSort(ItBegin it0, ItEnd it1, Int2Type<1>)
  {
    using namespace std;
    // sort
   cout << "Standart sorting algorithm was used. For iterators" << endl;
  }

  template <typename ItBegin, typename ItEnd>
  void doSort(ItBegin it0, ItEnd it1, Int2Type<2>)
  {
    using namespace std;
    // sort
    cout << "Fast sorting algorithm was used. For pointers" << endl;
  }
// based on the 3-rd dummy type parameter call will be dispatched to needed function
    int arr[3];
    MainTools::doSort(arr, arr + sizeof(arr) / sizeof(arr[0]), MainTools::Int2Type<1>());

    vector<int> v(3);
    MainTools::doSort(v.begin(), v.end(), MainTools::Int2Type<2>());
like image 21
spin_eight Avatar answered Apr 08 '23 05:04

spin_eight