I want to declare a map of function pointers where an enum is the key value,
and various function pointers are the mapped value. How do you do this?
I want to declare a map of function pointers where an enum is the key value,
and various function pointers are the mapped value. How do you do this?
Ubuntu Desktop
GCC/G++
Geany (for quick projects)
Anjuta (for larger things)
Then must all my functions return void and take an integer as their parameter? What if I want all different kinds of funcitons (that return differently, and take different params)?
Ubuntu Desktop
GCC/G++
Geany (for quick projects)
Anjuta (for larger things)
It's much easier with typedefs.
Also I would prefer member function pointers instead of C function pointers.
Code:class Object { typedef void (Object::*FUNCPTR)(const char *pSomething); typedef std::map<std::string, FUNCPTR> FuncMap; FuncMap m_MemberFunctionMap; };
But then how would you know how each item in the map is to be called and where the result goes?
I might be wrong.
Quoted more than 1000 times (I hope).Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
There is a way to do this using a union. MFC code utilizes this for their message map system. I'll show you what I came up with to remedy a similar problem.
Keep in mind this is just an example and I pulled a lot of it from MFC's method of handling message maps.
Be prepared because this is ugly.
I've since moved on to a map of member function pointers.
Code:#include <vector> #include <utility> #include "CBaseObject.h" ///////////////////////////////// //Script message map structures// ///////////////////////////////// //Forward delcaration of CBaseObject; class CBaseObject; //SCRIPT_MSG typedef typedef void (CBaseObject::*SCRIPT_MSG)(void); //SCRIPT_MSGMAP_ENTRY struct SCRIPT_MSGMAP_ENTRY { UINT nCommandID; UINT nFuncSig; SCRIPT_MSG pfn; //SCRIPT_MSGMAP_ENTRY(UINT nCommandID,UINT nFuncSig,SCRIPT_MSG pfn): //nCommandID(nCommandID),nFuncSig(nFuncSig),pfn(pfn) { } }; //SCRIPT_MSGMAP struct SCRIPT_MSGMAP { const SCRIPT_MSGMAP *pBaseMap; std::vector<SCRIPT_MSGMAP_ENTRY *> vEntries; }; //Function type signatures - to determine params enum SFuncSigs { SFSig_Param0_n =0, SFSig_Param1_n, //int fxn(DWORD) SFSig_Param2_n, //int fxn(DWORD,DWORD) SFSig_Param3_n //int fxn(DWORD,DWORD,DWORD) }; //Actual script function declarations union ScriptMsgMapFuncs { SCRIPT_MSG pfn; UINT (CBaseObject::*pfnParam1_n)(void); UINT (CBaseObject::*pfnParam2_n)(DWORD); UINT (CBaseObject::*pfnParam3_n)(DWORD,DWORD); }; //Declaration of the script message map //Adds a vector, parent object, and 3 new functions to CBaseObject #define DECLARE_SCRIPT_MSGMAP() \ protected: \ static std::vector<SCRIPT_MSGMAP_ENTRY *> m_vEntries; \ static CBaseObject *m_pParent; \ public: \ static const void SetupMessageMap(void); \ static const void AddHandler(UINT nCommandID,UINT nFuncSig,SCRIPT_MSG memberFxn); \ static const void SetParent(CBaseObject *pParent); //Must precede the start of every script message map #define BEGIN_SCRIPT_MSGMAP(theClass,baseClass) \ std::vector<SCRIPT_MSGMAP_ENTRY *> theClass::m_vEntries; \ CBaseObject *theClass::m_pParent=baseClass; \ const void theClass::AddHandler(UINT nCommandID,UINT nFuncSig,SCRIPT_MSG memberFxn) \ { \ SCRIPT_MSGMAP_ENTRY *pEntry=new SCRIPT_MSGMAP_ENTRY; \ pEntry->nCommandID=nCommandID; \ pEntry->nFuncSig=nFuncSig; \ pEntry->pfn=memberFxn; \ m_vEntries.push_back(pEntry); \ } \ const void theClass::SetupMessageMap(void) { //Script handler type 1 - unary script function #define ON_SCRIPT_CMD1(id,memberFxn) \ AddHandler(id,SFSig_Param1_n,(SCRIPT_MSG)memberFxn); //Script handler type 2 - binary script function #define ON_SCRIPT_CMD2(id,memberFxn) \ AddHandler(id,SFSig_Param2_n,(SCRIPT_MSG)memberFxn); //Script handler type 3 - trinary script function #define ON_SCRIPT_CMD3(id,memberFxn) \ AddHandler(id,SFSig_Param3_n,(SCRIPT_MSG)memberFxn); //Ends a script message map #define END_SCRIPT_MSGMAP }
Last edited by VirtualAce; 11-28-2008 at 01:16 PM.
Thank You all.
So I'm led to beleive using a map of function pointers is only useful if the functions themselves are relatively similar (and neccessarily similar in return type, and paramter list)?
Ubuntu Desktop
GCC/G++
Geany (for quick projects)
Anjuta (for larger things)
Well I was exploring the idea in my other thread about user access and the functions they can perform. I was thinking of the following abstraction:
but I don't think now that mapping function pointers is a good idea at least for my problem.Code:User makes request to access a function. If a user's key matches the function's key, they're allowed to carry out the action. The request is processed by a central mechanism (Access Control in my example here): Users --- Make Request ---> Access Control --- Look up function/key pair ---> Function
Ubuntu Desktop
GCC/G++
Geany (for quick projects)
Anjuta (for larger things)
With what parameters though? How will the user specify the parameters if he doesn't know the function?
You cad have a void* (fun)(void *) function and pass a struct, which will hold the parameters. And then cast it. As you do with POSIX Threads.
What you can do is this (if you want to work that way).
The User selects the type of functions. You have a std::map with keys and function pointers, that would be "vector<void*> (*fun)(vector<void*>&)"
The users selects the parameters. The parameters are inserted to a vector<void *>. You use the key to find the appropriate function from your map. You call the function. Its function will now how to cast the parameters.
Or, better, since the above might be considered unsafe/evil because of the casting, you have a "void* (*fun)(void*)", exactly like PThreads. You have a second std::map in which you have the same keys and void*. Each pointer will point at a specific class, which will have parameters stored in it. So the user will pass the parameters and the function will be called correctly. Like (w/o the second map):
or just do this if you have a way to take parameters with another way and putting them in mapPar(using two maps as I described above)Code:class par1 { int a; in b; }; class par2 { char a; char b; char c; }; ... cout << "Select key" cin >> key; ... cout << "Select parameters"; void* par = insertCorrectParameters(key); map[key](par); ... void* insertCorrectParameters(Keys key) { switch(key) { case 1: par1 par; //fill class; return (void*)par; case 2: par2 par; .... } } ... ... void* fun1(void* par) { par1 p = (par1*)par; ... } void* fun2(void* par) { par2 p = (par2*)par; ... }
and you 're done (I hope)Code:mapFun[key](mapPar[key]);
Last edited by C_ntua; 11-28-2008 at 06:28 PM.
At this point, you should just turn your function pointers into function objects, and thus be rid (or at least hide) the use of void* entirely.Originally Posted by C_ntua
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
Stop right there! This is C++, not C!
Even more horrible -_-You have a std::map with keys and function pointers, that would be "vector<void*> (*fun)(vector<void*>&)"
The users selects the parameters. The parameters are inserted to a vector<void *>. You use the key to find the appropriate function from your map. You call the function. Its function will now how to cast the parameters.
Or, better, since the above might be considered unsafe/evil because of the casting, youHorrors of horrors!have a "void* (*fun)(void*)", exactly like PThreads. You have a second std::map in which you have the same keys and void*. Each pointer will point at a specific class, which will have parameters stored in it. So the user will pass the parameters and the function will be called correctly. Like (w/o the second map):
Stop passing void* - it's evil, it's bad and it's not C++!
This kindof sounds like the job boost::bind. You create a functor, in which you might store a function along with its parameters (ie, bind them). Then you pass them along to the function which checks the permission and executes it if it's A-OK.
C_ntua, I seriously suggest you start boosting up your knowledge of templates and designs, like functors.
Passing void* is the old C way, which you should avoid like the plague in today's C++ - it offers so much more better designs!
functors would be one solution.
The other solution, more C-like but still workable, assuming that the number of keys and functions are equal and relatively small would be to use a fixed class/struct that holds pairs of keys and functions, where each function is declared correctly with actual return value and parameters.
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
Wasn't aware of function objects, so looked 'em up a bit. Just to see if I understand the concept of them. Could you do something like:
So, doFun will practically do f1() which will do sum += a+b? Or will my code, most likely, do nothing ?Code:class fun1 { int a, b; int sum; public: void setVal(int c, int d){a = c; b = d;} int getVal(){return sum;} void operator() () {sum += a + b;} fun1(){sum = 0;} }; //general function template <class Fun> void doFun(Fun fun) { fun(); } //in main fun1 f1; f1.getVal(2, 3); doFun<fun1>(f1); //or doFun(f1) ?? int sum = f1.getVal();