2

Here is my code.

#include <map>
#include <string>
#include <algorithm>

class maptest {
public:
   int doubler(int val) { return val * 2; }
   int halver(int val) { return val / 2; }
   int negativer(int val) { return val > 0 ? -val : val; }
};


int main() {

   const char* const ID[] = {"doubler", "halver", "negativer" };
   int ID_SIZE = sizeof(ID) / sizeof(*ID);   

   //signature of maths functions
   typedef int (maptest::*mathfunc)(int);


   mathfunc mfuncs[] = { &maptest::doubler, &maptest::halver, &maptest::negativer};

   std::map<std::string, mathfunc> mathmap;   

   for(int i = 0; i < ID_SIZE; ++i) {
       mathmap.insert(std::make_pair(ID[i], mfuncs[i]));
   }

   //C2064: term does not evaluate to a function taking 1 argument
   int result = *mathmap["doubler"](3);

   return 0;
}

I think this would work if there was no parameter to be passed to the functions. But how do I pass a parameter in this way?

Angus Comber
  • 9,316
  • 14
  • 59
  • 107

2 Answers2

3

Your mathfuncs are member functions, so you need an object on which to invoke them:

maptest mt;
int result = (mt.*(mathmap["doubler"]))(3);

Alternatively, you could make your member functions static:

class maptest {
public:
   static int doubler(int val) { return val * 2; }
   static int halver(int val) { return val / 2; }
   static int negativer(int val) { return val > 0 ? -val : val; }
};

And then define mathfunc accordingly:

typedef int (*mathfunc)(int);

And this would allow you to invoke them the way you are invoking them in your original post:

typedef int (*mathfunc)(int);

Notice, that a way to make this design more flexible is to make use of std::function, which would allow you to pass any type of callable object. For instance:

typedef std::function<int(int)> mathfunc;

mathfunc mfuncs[] = {
    &maptest::doubler,
    &maptest::halver,
    &maptest::negativer,
    [] (int i) { return i * 2; } // <== A LAMBDA...
    };
Community
  • 1
  • 1
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • The bracketing on (mt.*(mathmap["doubler"])) is confusing. Why do you need the outer bracketing, ie the out brackets here: (mt.*(mathmap["doubler"])) ? – Angus Comber May 15 '13 at 12:45
  • @user619818: It's not needed, I just thought it made things clearer. Perhaps I was wrong ;) – Andy Prowl May 15 '13 at 12:46
  • On my VS2008 compiler it is needed. No matter. – Angus Comber May 15 '13 at 13:19
  • @user619818: Sorry, I misunderstood your question. The outer parentheses are needed, not the inner one. In other words, this compiles: `(mt.*mathmap["doubler"])(3);`, but this doesn't: `mt.*mathmap["doubler"](3);` – Andy Prowl May 15 '13 at 13:20
  • @user619818: That is because of how the grammar is specified. Without parentheses the compiler would try to parse it as `mt.*(mathmap["doubler"](3))` – Andy Prowl May 15 '13 at 14:17
1

You are invoking non static member function.

do the following.

 maptest  t;

 int (maptest::*tptr) (int) =  mathmap["doubler"];

 int result =   (t.*tptr)(2);

Hope this helps.

Whoami
  • 13,930
  • 19
  • 84
  • 140