How to declare a map of function pointers?

This is a discussion on How to declare a map of function pointers? within the C++ Programming forums, part of the General Programming Boards category; I want to declare a map of function pointers where an enum is the key value, and various function pointers ...

  1. #1
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391

    How to declare a map of function pointers?

    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)

  2. #2
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,428
    Code:
    std::map<my_enum, void (*)(int)> my_map;
    Change as desired.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    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)

  4. #4
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,428
    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.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,590
    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;
    };

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    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.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,590
    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 12:16 PM.

  8. #8
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    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)

  9. #9
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,428
    Well, apparently so. What are you trying to do?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    Quote Originally Posted by Elysia View Post
    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:
    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
    but I don't think now that mapping function pointers is a good idea at least for my problem.
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  11. #11
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    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):
    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;
        ...
    }
    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:
    mapFun[key](mapPar[key]);
    and you 're done (I hope)
    Last edited by C_ntua; 11-28-2008 at 05:28 PM.

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,410
    Quote Originally Posted by C_ntua
    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.
    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.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,428
    Quote Originally Posted by C_ntua View Post
    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.
    Stop right there! This is C++, not C!

    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.
    Even more horrible -_-

    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):
    Horrors of horrors!
    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!
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    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.

  15. #15
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Quote Originally Posted by laserlight View Post
    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.
    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:

    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();
    So, doFun will practically do f1() which will do sum += a+b? Or will my code, most likely, do nothing ?

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Seg Fault in Compare Function
    By tytelizgal in forum C Programming
    Replies: 1
    Last Post: 10-25-2008, 03:06 PM
  2. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  3. Please Help - Problem with Compilers
    By toonlover in forum C++ Programming
    Replies: 5
    Last Post: 07-23-2005, 10:03 AM
  4. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 09:33 AM
  5. linked list recursive function spaghetti
    By ... in forum C++ Programming
    Replies: 4
    Last Post: 09-02-2003, 02:53 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21