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?
Printable View
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?
Change as desired.Code:std::map<my_enum, void (*)(int)> my_map;
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)?
Then you would have a problem...
I'm not sure of the solution. I'm sure boost has some interesting containers to store stuff, though.
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?
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 }
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)?
Well, apparently so. What are you trying to do?
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
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]);
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.Quote:
Originally Posted by C_ntua
Stop right there! This is C++, not C!
Even more horrible -_-Quote:
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!Quote:
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
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();