Thread: How to declare a map of function pointers?

  1. #16
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    doFun(f1) works just fine. You have a typo in the first getVal should be setVal, but otherwise, yes, it should work.
    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.

  2. #17
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Just a small clarification: how come you don't use the <> since you have a template function?

  3. #18
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    <> is only required for classes, or when the compiler cannot deduce the type of the template parameter. In this case, since you pass an object of a certain type, the compiler can easily deduce the actual type of the template parameter.
    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.

  4. #19
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    If I knew more about templates, I'd probably know the answer to the question I'm about to ask, but can templates take function pointers at their type? And if so, could the magic of templates/specialization be used to allow function pointers of any return type/parameter list?
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  5. #20
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    I know what I've been trying to do hasn't been exactly clear. Here's a small example I wrote up. Basically I'm looking for a more elegant way to do what I've got here:

    Code:
    #include <iostream>
    #include <map>
    
    typedef unsigned char uchar;
    
    enum ACCESS_TYPE{
    	ACCESS_1,
    	ACCESS_2
    };
    
    void fxn1(){
    	std::cout << "Function 1.\n";
    }
    
    int fxn2( int n ){
    	std::cout << "Function 2.\n";
    	return n;
    }
    
    class User{
    
    	public:
    		User( uchar key ) : key( key ) {};
    		const uchar& getUserKey() const { return key; }
    		void setUserKey( uchar newKey ){ key = newKey; }
    		
    	private:
    		uchar key;
    };
    
    void checkUserAccess( std::map<ACCESS_TYPE, uchar>& fxnMap, ACCESS_TYPE accessType, User& user ){
    
    	std::map<ACCESS_TYPE, uchar>::iterator it = fxnMap.find( accessType );
    	
    	switch( accessType ){
    		case( ACCESS_1 ):{
    			if( ( it->second & user.getUserKey() ) == it->second ){
    				std::cout << "User has access.\n";
    				fxn1();
    			}
    			else
    				std::cout << "User does not have access.\n";
    			break;
    		}
    		case( ACCESS_2 ):{
    			if( ( it->second & user.getUserKey() ) == it->second ){
    				std::cout << "User has access.\n";
    				int x = fxn2( 5 );
    			}
    			else
    				std::cout << "User does not have access.\n";
    			break;
    		}
    	}
    }
    
    int main(){
    
    	User John( 0x0B );
    	
    	std::map<ACCESS_TYPE, uchar> fxnMap;
    	fxnMap.insert( std::pair<ACCESS_TYPE, uchar>( ACCESS_1, 0x04 ) );
    	fxnMap.insert( std::pair<ACCESS_TYPE, uchar>( ACCESS_2, 0x08 ) );
    	
    	checkUserAccess( fxnMap, ACCESS_1, John );
    	checkUserAccess( fxnMap, ACCESS_2, John );
    	
    	return 0;
    }
    Basically the whole checkUserAccess mechanism just seems broke in design and implementation.
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  6. #21
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    As you are using bit fiddling to do the work anyway, this is a much simpler form:

    Code:
    #include <iostream>
    #include <map>
    
    typedef unsigned char uchar;
    
    enum ACCESS_TYPE{
    	ACCESS_1 = 0x04,
    	ACCESS_2 = 0x08
    };
    
    void fxn1(){
    	std::cout << "Function 1.\n";
    }
    
    int fxn2( int n ){
    	std::cout << "Function 2.\n";
    	return n;
    }
    
    class User{
    
    	public:
    		User( uchar key ) : key( key ) {};
    		const uchar& getUserKey() const { return key; }
    		void setUserKey( uchar newKey ){ key = newKey; }
    		
    	private:
    		uchar key;
    };
    
    void checkUserAccess(ACCESS_TYPE accessType, User& user ){
    	
    	switch( accessType ){
    		case( ACCESS_1 ):{
    			if( ( ACCESS_1 & user.getUserKey() ) == ACCESS_1 ){
    				std::cout << "User has access.\n";
    				fxn1();
    			}
    			else
    				std::cout << "User does not have access.\n";
    			break;
    		}
    		case( ACCESS_2 ):{
    			if( ( ACCESS_2 & user.getUserKey() ) == ACCESS_2 ){
    				std::cout << "User has access.\n";
    				int x = fxn2( 5 );
    			}
    			else
    				std::cout << "User does not have access.\n";
    			break;
    		}
    	}
    }
    
    int main(){
    
    	User John( 0x0B );
    	
    	checkUserAccess( ACCESS_1, John );
    	checkUserAccess( ACCESS_2, John );
    	
    	return 0;
    }

  7. #22
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    Ahhh, that's what happens when I NEVER use enums! My biggest weakness: my C++ repertoire! That's really good actually, thanx phanomotap!
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  8. #23
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    In the future, you might try to do a better job of telling the people trying to help you what you actually want to do. The people who've posted so far definitely would have helped you with that a long time ago.

    Soma

  9. #24
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Just a small note. Even though you don't seem to need something like a function object or another implementation noted above, if you have a lot of access type it would be a good idea to use them. Instead of writing fxn1() or int x = fxn2(5) in your example you could just write something general, like doFun(fxn1), doFun(fxn2).
    That will have the advantage that if you change fxn1, or fxn2 you will just change the class and won't risk making mistakes from rewriting things in your checkUsersAccess functions. In a way you will have a more clear code.

  10. #25
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    Well, what phanomotap posted helps me only somewhat. It's certainly not the end-all answer to my problem. Like, where do the parameters come from if different functions require different param lists? That's a problem I still need to tackle.

    In this app, I can't make any assumptions like how many different functions there might be, and especially what kind of param lists of those different functions have.

    I'm still seeking a more general solution to this problem and I will have to explore many of the ideas others have posted here. Right now, Bubba's suggestion of member function pointers seems to be one good option, and I'll explore that and others more in depth.

    Forgive me if I didn't clearly define the problem, but mine is a rather complex one, and at this point I'm only coming up with "It could be done this way" solutions and not "It should be done this way" solutions. When I find that, my job will be done.

    In addition, other programmers are laying the infrastructure for this app (developing only the absolute minimum required by Jan 15), and I don't know if any model/solution I come up with will actually fit with what they have (this is the unfortunate process of government & government-contract software projects).
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  11. #26
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    *shrug*

    I looked up this up for you because I was curious if I still had it.

    Creating and parsing some generic representation of both the parameter lists and the return type in a manager of some sort is the only way you will be able to do what you may want.

    However, from the ambiguous way you are describing your goal it also may be as simple as mapping a 'void (*)()' to any other type by using a simple polymorphic function object. (This has already been suggested.)

    The point is, what do you really want?

    "Like, where do the parameters come from if different functions require different param lists?", for example, isn't helpful. Where do you want them to come from? At what point will you have enough information to know what arguments should be passed? Are the arguments the same for any given association? Or are they always different?

    Soma

    Code:
    #include <algorithm>
    #include <cstdlib>
    #include <iostream>
    #include <map>
    #include <sstream>
    #include <stdexcept>
    #include <string>
    #include <vector>
    
    struct vafb
    {
       struct association
       {
          static const unsigned long vfv = 0;
          static const unsigned long sfv = 1;
          static const unsigned long sfs = 2;
          static const unsigned long sfss = 3;
          static const unsigned long sfm = 4;
       };
       vafb(){}
       virtual ~vafb(){}
       virtual void vfv(){throw std::runtime_error("Invalid Function!");}
       virtual std::string sfv(){throw std::runtime_error("Invalid Function!");}
       virtual std::string sfs(const std::string &){throw std::runtime_error("Invalid Function!");}
       virtual std::string sfss(const std::string &, const std::string &){throw std::runtime_error("Invalid Function!");}
       virtual std::string sfm(const std::vector<std::string> &){throw std::runtime_error("Invalid Function!");}
       virtual unsigned long vafb_type() = 0;
    };
    
    template <typename return_t, typename parameter_1_t, typename parameter_2_t> struct auto_vafb: public vafb
    {
       typedef return_t (*function_type)(parameter_1_t, parameter_2_t);
       auto_vafb(function_type function): function_m(function)
       {
       }
       virtual std::string sfss(const std::string & parameter_1, const std::string & parameter_2)
       {
          std::istringstream parameter_1_stream(parameter_1);
          std::istringstream parameter_2_stream(parameter_2);
          parameter_1_t modified_parameter_1;
          parameter_2_t modified_parameter_2;
          std::ostringstream return_value_stream;
          parameter_1_stream >> modified_parameter_1;
          parameter_2_stream >> modified_parameter_2;
          return_value_stream << function_m(modified_parameter_1, modified_parameter_2);
          return(return_value_stream.str());
       }
       virtual unsigned long vafb_type()
       {
          return(vafb::association::sfss);
       }
       function_type function_m;
    };
    
    template <typename return_t, typename parameter_1_t> struct auto_vafb<return_t, std::vector<parameter_1_t>, void>: public vafb
    {
       typedef return_t (*function_type)(const std::vector<parameter_1_t> &);
       auto_vafb(function_type function): function_m(function)
       {
       }
       virtual std::string sfm(const std::vector<std::string> & parameter_1)
       {
          const std::vector<std::string>::size_type size(parameter_1.size());
          std::vector<parameter_1_t> values(size);
          for(std::vector<std::string>::size_type cursor(0); cursor < size; ++cursor)
          {
             std::istringstream parameter_stream(parameter_1[cursor]);
             parameter_1_t modified_parameter;
             parameter_stream >> modified_parameter;
             values[cursor] = modified_parameter;
          }
          std::ostringstream return_value_stream;
          return_value_stream << function_m(values);
          return(return_value_stream.str());
       }
       virtual unsigned long vafb_type()
       {
          return(vafb::association::sfm);
       }
       function_type function_m;
    };
    
    template <typename return_t, typename parameter_1_t> struct auto_vafb<return_t, parameter_1_t, void>: public vafb
    {
       typedef return_t (*function_type)(parameter_1_t);
       auto_vafb(function_type function): function_m(function)
       {
       }
       virtual std::string sfs(const std::string & parameter_1)
       {
          std::istringstream parameter_1_stream(parameter_1);
          parameter_1_t modified_parameter_1;
          std::ostringstream return_value_stream;
          parameter_1_stream >> modified_parameter_1;
          return_value_stream << function_m(modified_parameter_1);
          return(return_value_stream.str());
       }
       virtual unsigned long vafb_type()
       {
          return(vafb::association::sfs);
       }
       function_type function_m;
    };
    
    template <typename return_t> struct auto_vafb<return_t, void, void>: public vafb
    {
       typedef return_t (*function_type)();
       auto_vafb(function_type function): function_m(function)
       {
       }
       virtual std::string sfv()
       {
          std::ostringstream return_value_stream;
          return_value_stream << function_m();
          return(return_value_stream.str());
       }
       virtual unsigned long vafb_type()
       {
          return(vafb::association::sfv);
       }
       function_type function_m;
    };
    
    template <> struct auto_vafb<void, void, void>: public vafb
    {
       typedef void (*function_type)();
       auto_vafb(function_type function): function_m(function)
       {
       }
       virtual void vfv()
       {
          function_m();
       }
       virtual unsigned long vafb_type()
       {
          return(vafb::association::vfv);
       }
       function_type function_m;
    };
    
    template <typename return_t, typename parameter_1_t, typename parameter_2_t> vafb * craft_vafb(return_t (*function)(parameter_1_t, parameter_2_t))
    {
       return(new auto_vafb<return_t, parameter_1_t, parameter_2_t>(function));
    };
    
    template <typename return_t, typename parameter_1_t> vafb * craft_vafb(return_t (*function)(const std::vector<parameter_1_t> &))
    {
       return(new auto_vafb<return_t, std::vector<parameter_1_t>, void>(function));
    };
    
    template <typename return_t, typename parameter_1_t> vafb * craft_vafb(return_t (*function)(parameter_1_t))
    {
       return(new auto_vafb<return_t, parameter_1_t, void>(function));
    };
    
    template <typename return_t> vafb * craft_vafb(return_t (*function)())
    {
       return(new auto_vafb<return_t, void, void>(function));
    };
    
    vafb * craft_vafb(void (*function)())
    {
       return(new auto_vafb<void, void, void>(function));
    };
    
    struct vafb_manager
    {
       vafb_manager()
       {
       }
       ~vafb_manager()
       {
          std::map<std::string, vafb *>::const_iterator cursor(vafb_m.begin());
          std::map<std::string, vafb *>::const_iterator end(vafb_m.end());
          while(cursor != end)
          {
             delete cursor->second;
             ++cursor;
          }
       }
       template <typename function_type_t> bool add(const std::string & name, std::string & output, function_type_t function)
       {
          const std::map<std::string, vafb *>::iterator fun(vafb_m.find(name));
          if(fun != vafb_m.end())
          {
             output = "function already exists";
             return(false);
          }
          vafb_m[name] = craft_vafb(function);
          return(true);
       }
       bool process(const std::string & line, std::string & output)
       {
          const std::string::const_iterator cursor_line(line.begin());
          const std::string::const_iterator end_line(line.end());
          const std::string::const_iterator cursor_function_name(cursor_line);
          const std::string::const_iterator end_function_name(std::find(cursor_function_name, end_line, ' '));
          const std::string function_name(cursor_function_name, end_function_name);
          const std::map<std::string, vafb *>::iterator function(vafb_m.find(function_name));
          if(function == vafb_m.end())
          {
             output = "function not in library";
             return(false);
          }
          const unsigned long vafb_type(function->second->vafb_type());
          if(vafb::association::vfv == vafb_type)
          {
             output = "";
             function->second->vfv();
          }
          if(vafb::association::sfv == vafb_type)
          {
             output = function->second->sfv();
          }
          if(vafb::association::sfs == vafb_type)
          {
             if(end_line == end_function_name)
             {
                output = "function takes one argument";
                return(false);
             }
             const std::string::const_iterator cursor_parameter(end_function_name);
             const std::string::const_iterator end_parameter(end_line);
             const std::string parameter_1(cursor_parameter + 1, end_parameter);
             output = function->second->sfs(parameter_1);
          }
          if(vafb::association::sfss == vafb_type)
          {
             if(end_line == end_function_name)
             {
                output = "function takes two arguments";
                return(false);
             }
             const std::string::const_iterator cursor_parameter_1(end_function_name);
             const std::string::const_iterator end_parameter_1(std::find(cursor_parameter_1 + 1, end_line, ' '));
             const std::string::const_iterator cursor_parameter_2(end_parameter_1);
             const std::string::const_iterator end_parameter_2(end_line);
             const std::string parameter_1(cursor_parameter_1 + 1, end_parameter_1);
             const std::string parameter_2(cursor_parameter_2 + 1, end_parameter_2);
             output = function->second->sfss(parameter_1, parameter_2);
          }
          if(vafb::association::sfm == vafb_type)
          {
             std::vector<std::string> parameters;
             std::string::const_iterator cursor_parameter(end_function_name);
             std::string::const_iterator end_parameter(std::find(cursor_parameter + 1, end_line, ' '));
             while(end_line != cursor_parameter)
             {
                parameters.push_back(std::string(cursor_parameter + 1, end_parameter));
                cursor_parameter = end_parameter;
                end_parameter = std::find(cursor_parameter + 1, end_line, ' ');
             }
             output = function->second->sfm(parameters);
          }
          return(true);
       }
       std::map<std::string, vafb *> vafb_m;
    };
    
    void clear_vafb()
    {
       std::cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
    }
    
    unsigned long random_vafb()
    {
       return(std::rand());
    }
    
    unsigned long gid_vafb(unsigned long value)
    {
       return(value ^ 0xFF00FF00);
    }
    
    double devide_vafb(double numerator, double denominato)
    {
       return(numerator / denominato);
    }
    
    struct my_short_test
    {
       friend std::ostream & operator << (std::ostream & out, const my_short_test & value)
       {
          out << value.value_m;
          return(out);
       }
       friend std::istream & operator >> (std::istream & in, my_short_test & value)
       {
          short temp(0);
          in >> temp;
          value = temp;
          return(in);
       }
       my_short_test(): value_m(0)
       {
       }
       explicit my_short_test(short value): value_m(value)
       {
       }
       my_short_test(const my_short_test & value): value_m(value.value_m)
       {
       }
       my_short_test & operator = (short value)
       {
          value_m = value;
          return(*this);
       }
       my_short_test & operator = (const my_short_test & value)
       {
          value_m = value.value_m;
          return(*this);
       }
       my_short_test & operator += (short value)
       {
          value_m += value;
          return(*this);
       }
       my_short_test & operator += (const my_short_test & value)
       {
          value_m += value.value_m;
          return(*this);
       }
       short value_m;
    };
    
    my_short_test sum_vafb(const std::vector<my_short_test> & values)
    {
       const std::vector<std::string>::size_type size(values.size());
       my_short_test temp(0);
       if(0 == size)
       {
          return(temp);
       }
       for(std::vector<std::string>::size_type cursor(0); cursor < size; ++cursor)
       {
          temp += values[cursor];
       }
       return(temp);
    }
    
    int main(int argc, char ** argv)
    {
       std::string line;
       std::string output;
       vafb_manager manager;
       manager.add("clear", output, clear_vafb);
       manager.add("random", output, random_vafb);
       manager.add("gid", output, gid_vafb);
       manager.add("devide", output, devide_vafb);
       manager.add("sum", output, sum_vafb);
       while(std::getline(std::cin, line))
       {
          if(!manager.process(line, output))
          {
             std::cout << "error::manager:" << output << '\n';
          }
          else
          {
             if("" != output)
             {
                std::cout << " -> " << output << '\n';
             }
          }
       }
       return(0);
    }

  12. #27
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Forgive me if I didn't [...] solutions.
    Posting some of those possible solutions may reveal the real solution.

    Soma

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, 10:33 AM
  5. linked list recursive function spaghetti
    By ... in forum C++ Programming
    Replies: 4
    Last Post: 09-02-2003, 02:53 PM