CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 2 of 2 FirstFirst 12
Results 16 to 20 of 20
  1. #16
    Join Date
    Nov 2010
    Posts
    105

    Re: How to pair/multimap <int, pointer to a function>?

    Thanks! Now it's clearer to me. So I should move the multimap outside of the class and after an object of that class is created, right?

  2. #17
    Join Date
    Apr 1999
    Posts
    27,449

    Re: How to pair/multimap <int, pointer to a function>?

    Quote Originally Posted by acppdummy View Post
    Thanks! Now it's clearer to me. So I should move the multimap outside of the class and after an object of that class is created, right?
    The bottom line is that you need an object created to call non-static member functions, whether or not you're calling the function using a pointer. That's just basic C++.
    Code:
    class X
    {
        public:
          void DoSomething();
    };
    
    int main()
    {
       // how do you call DoSomething()?
       // not like this:
       // X::DoSomething();
       //...
       // like this -- create an object...
       X someObject;
       someObject.DoSomething();
    }
    So a pointer to the non-static member function has to follow the same rules, thus the syntax I showed you earlier.

    Regards,

    Paul McKenzie

  3. #18
    Join Date
    Nov 2010
    Posts
    105

    Re: How to pair/multimap <int, pointer to a function>?

    Understood. Thank you very much!

  4. #19
    Join Date
    Nov 2010
    Posts
    105

    Question Re: How to pair/multimap <int, pointer to a function>?

    OK I hope I am getting close to the right track: failed to find the syntax to call std::mem_fun and confused by std::function and std::bind, I found this:
    http://www.goingware.com/tips/member-pointers.html
    ... One of the best uses for member function pointers is caching the outcome of a decision over which of several member functions should be called in a particular circumstance. If a decision is always going to yield the same result, then it may be faster and even cleaner to make the decision just once ahead of time, then store the outcome in the form of a member function pointer. This is especially advantageous when the decision will be made repeatedly in a loop. ...
    This is exactly what I needed! The example code follows:
    Code:
    #include <exception>  
    class Test {
     	public:
     		Test( long inFactor );
      		long TimesOne( long inToMultiply ) const;
     		long TimesTwo( long inToMultiply ) const;
     		long TimesThree( long inToMultiply ) const;
      		long MultiplyIt( long inToMultiply ) const;
     	private:
     		typedef long (Test::*Multiplier)( long inToMultiply ) const;
      		long       mFactor;
     		Multiplier mMultFuncPtr;
      		static Multiplier GetFunctionPointer( long inFactor ); };
      Test::Test( long inFactor )
     	: mFactor( inFactor ),
     	  mMultFuncPtr( GetFunctionPointer( mFactor ) ) {
     	return; }
      Test::Multiplier Test::GetFunctionPointer( long inFactor ) {
     	switch ( inFactor ){
    	// Decision only made once!
     		case 1:
     			return &Test::TimesOne;
     			break;
      		case 2:
     			 return &Test::TimesTwo;
     			break;
      		case 3:
     			 return &Test::TimesThree;
     			break;
     	 		default:
     			throw std::exception(); 	} } 			
     long Test::MultiplyIt( long inToMultiply ) const {
     	// Using cached decision result
     	return (this->*mMultFuncPtr)( inToMultiply );	 }
      void MultiplyThem( long inFactor ) {
     	Test myTest( 2 );
     	 	long product;
      	for ( long i = 0; i < 1000000; ++i )
     		product = myTest.MultiplyIt( i ); }
    Then I found this:
    http://www.codeguru.com/cpp/cpp/arti...r-Function.htm
    ... An important application of pointer-to-member functions is to generate the response events according to inputs. ...
    Again exactly what I am trying to do! The example code follows:
    Code:
    1. #include <stdio.h>
    2. #include <string>
    3. #include <iostream>
    4. class Printer{//An abstract printing machine
    5. public:
    6. void Copy(char * buff, const char * source){//copy the file
    7. strcpy(buff, source);
    8. }
    9. void Append(char * buff, const char * source){//extend the file
    10. strcat(buff, source);
    11. }
    12. };
    13. enum OPTIONS { COPY, APPEND };//two possible commands in the menu.
    14. typedef void(Printer::*PTR) (char*, const char*);//pointer-to-member function
    15. void working(OPTIONS option,
    16. Printer* machine,
    17. char* buff,
    18. const char* infostr){
    19. PTR pmf[2]= {&Printer::Copy, &Printer::Append}; //pointer array
    20. switch (option){
    21. case COPY:
    22. (machine->*pmf[COPY])(buff, infostr);
    23. break;
    24. case APPEND:
    25. (machine->*pmf[APPEND])(buff, infostr);
    26. break;
    27. }
    28. }
    29. int main(){
    30. OPTIONS option;
    31. Printer machine;
    32. char buff[40];//target
    33. working(COPY, &machine, buff, "Strings ");
    34. working(APPEND, &machine, buff, "are concatenated! ");
    35. std::cout<<buff<<std::endl;
    36. }
    37. Output:
    38. Strings are concatenated!
    Following the two examples I put together something like this:
    Code:
    class MyClass { 
    ...
    int map_formula(int id, ...);
    ...
    void fna();
    void fnb();
    ...
    void run(int id, ...);
    ...
    }
    
    typedef void(MyClass::*memfnptr_t) ();//pointer-to-member function
    
    multimap<int, memfnptr_t> mm_id_fn;
    
    int MyClass::map_formula(int id, ...){
    // will be called multiple times with different values of id to construct the multimap
    ...
    mm_id_fn.insert(pair<int,memfnptr_t>(id,&MyClass::fna));
    ...
    mm_id_fn.insert(pair<int,memfnptr_t>(id,&MyClass::fnb)); 
    ...
    }
    
    void MyClass::run(int id, ...){
        multimap<int,memfnptr_t>::iterator it;
        pair<multimap<int,memfnptr_t>::iterator, multimap<int,memfnptr_t>::iterator> ret;
        it = mm_id_fn.find(id);
        if (it!=mm_id_fn.end()){
            ret = mm_id_fn.equal_range(id); // find all functions pointed by id
            for (it = ret.first; it != ret.second; ++it){
                memfnptr_t fn=(*it).second;
                (this->*fn)();
            }
            cout << endl;
            
        }
    
    }
    It compiles and seems to run OK but I am not sure if it is legal or correct. Please comment. Thanks!
    Last edited by acppdummy; May 25th, 2012 at 08:55 AM.

  5. #20
    Join Date
    Nov 2010
    Posts
    105

    Question Re: How to pair/multimap <int, pointer to a function>?

    I have to move the multimap back into the class otherwise different instances of the class share the same multimap and interfere with one another. Now the code looks something like

    Code:
    class MyClass;
    
    typedef void(MyClass::*memfnptr_t) ();//pointer-to-member function
    
    class MyClass { 
    ...
    multimap<int, memfnptr_t> mm_id_fn;
    ...
    int map_formula(int id, ...);
    ...
    void fna();
    void fnb();
    ...
    void run(int id, ...);
    ...
    }
    
    ... // the rest is the same as before
    It seems to work so far. Please comment if there is anything wrong with this approach. Also I wonder if the typedef can be hidden inside the class as well? Thanks!

Page 2 of 2 FirstFirst 12

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured