Store pointers to member function in the map

10,565

Looks fine to me, but for the fact that descrToFuncMap needs to be declared static if you intend to initialise it from inside the static function Initialize().

If you want to make sure that Initialize() gets called, and gets called just once, you can use the Singleton pattern. Basically, if you aren't doing multithreading, that just means wrapping descrToFuncMap inside its own class (called say FuncMap) with a private constructor that calls Initialize(). Then you add a static local variable of type FuncMap to Processor::Process() -- because the variable is static, it persists and is only initialised once.

Example code (I now realise that friend isn't really necessary here):

class Processor {
private:
    typedef double (MyClass::*MemFuncGetter)();

    class FuncMap {
    public:
        FuncMap() {
            descrToFuncMap["X"]=&MyClass::GetX;
            descrToFuncMap["SomethingElse"]=&MyClass::GetSomethingElse;
            descrToFuncMap["RR"]=&MyClass::GetRR;
            descrToFuncMap["T"]=&MyClass::GetT;
        }

        // Of course you could encapsulate this, but its hardly worth
        // the bother since the whole class is private anyway.
        map<std::string, MemFuncGetter> descrToFuncMap;
    };

public:
    void Process(Myclass m, string);
};

void Processor::Process(MyClass ms, const std::string& key) {
    static FuncMap fm;      // Only gets initialised on first call
    map<std::string, Getter>::iterator found=fm.descrToFuncMap.find(key);
    if(found!=fm.descrToFuncMap.end()) {
        MemFuncGetter memFunc=found->second;
        double dResult=(ms).*memFunc();    
        std::cout<<"Command="<<key<<", and result="<<result<<std::end;      
    }
}

This is not the "true" Singleton pattern as different functions could create their own, separate instances of FuncMap, but it's enough for what you need. For "true" Singleton, you would declare FuncMap's constructor private and add a static method, say getInstance(), which defined the one-and-only instance as a static variable and returned a reference to that. Processor::Process() would then use this with

FuncMap& fm = FuncMap::getInstance();
Share:
10,565
Admin
Author by

Admin

Updated on June 20, 2022

Comments

  • Admin
    Admin about 2 years

    I'd like to map string to an instance member functions, and store each mapping in the map.

    What is the clean way of doing something like that?

    class  MyClass
    {
       //........
       virtual double GetX();
       virtual double GetSomethingElse();
       virtual double GetT();
       virtual double GetRR();
       //........
    };
    
    
    class Processor
    {
     private:
          typedef double (MyClass::*MemFuncGetter)();
          static map<std::string, MemFuncGetter> descrToFuncMap;
    
     public:
            static void Initialize();
            void Process(Myclass m, string);
    };
    
    void Processor::Initialize()
    {
    
         descrToFuncMap["X"]=&MyClass::GetX;
         descrToFuncMap["SomethingElse"]=&MyClass::GetSomethingElse;
         descrToFuncMap["RR"]=&MyClass::GetRR;
         descrToFuncMap["T"]=&MyClass::GetT;
    };
    void Processor::Process(MyClass ms, const std::string& key)
    {
         map<std::string, Getter>::iterator found=descrToFuncMap.find(key);
         if(found!=descrToFuncMap.end())
         {
            MemFuncGetter memFunc=found->second;
            double dResult=(ms).*memFunc();    
            std::cout<<"Command="<<key<<", and result="<<result<<std::end;      
          }
     }  
    

    let me know if you see a problem with this approach and what are common idioms for that?

    Perhaps, I should use if-else-if statement chain, given that I have a limited number of member functions, instead of a confusing map of func pointers

    BTW, I found some of the useful info here in the c++-faq-lite

  • Admin
    Admin over 15 years
    well yea, obviously I would pass string as a const to reference. My question is perhaps, I should use if-statement chain given that I have a limited number of member functions instead of a confusing map of func pointers
  • Admin
    Admin over 15 years
    yea it is static (fixed it). I like the idea of a private friend class. Would you demonstrate it with an example? Thanks
  • Admin
    Admin over 15 years
    Why doesn't it call an overriden function?