954,500 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Constructor function call problem

Em.. the problem is quite simple. This is the error output on when I try to build this.

error: no matching function for call to ‘Console::action_new(const char [5], const char [23], <unresolved overloaded function type>)’


This is the source...

/*
	Author: Wolter Hellmund
	Email:	whellmundv@gmail.com
	---------------------------------------
	This is an automatized console version of KeyHolder.
	It was made to make the code simpler and smaller.
	---------------------------------------
	Copyright (c) 2008
*/

#include <iostream>
#include <string>
#include <map>
#include <vector>

using std::map;
using std::string;
using std::vector;
using std::cout;
using std::cin;
using std::endl;

class Console
{
	// Private variables
	 int finished, success;
    string input;

public:
	// The Base structure of the console and resposible for automation.
    struct Action
    {
        string help;    		// Action documentation
        int (*call)();	// Function to call
    };
    map<string,Action> action_index;

    // Functions
	int quit()
    {
        finished = 1;
        return 0;
    }

    void report_error(string error_kind)
    {
        if (error_kind == "com")
        {
            cout << "Invalid command. Type \"help\" for a list of commands." << endl;
        }
    }

    int help()
    {
    	cout << "Action:\t\t\tDescription:" << endl;
    	// For each element in the action_list, print it's name and description
    	for (map<string,Action>::iterator counter = action_index.begin(); counter != action_index.end(); counter++)			//(vector<string>::iterator counter = action_list.begin(); counter != action_list.end(); counter++)
    	{
    		cout
    		// Print command's name
					<< counter->first
					<< "\t\t\t"
    		// Print command's description
					<< counter->second.help
					<< endl;
    	}
    	return 0;
    }

	 void read()
	{
		// Asks for input, and reads it
		while (finished != 1)
		{
			success = 0;
			cout << ">>>"; getline(cin,input);
			for (map<string,Action>::iterator counter = action_index.begin(); counter != action_index.end(); counter++)
			{
				if (input == counter->first)
				{
					success = 1;
					(action_index[ counter->first ].call)();
					//(this->*action_index[input].call)();
					break;
				}
			}
			if (!success) report_error("com");
		}
	}

	// Action creator
    void action_new( string name, string help, int (*function)() )
    {
        action_index[name].help = help;		// Sets action's help string to the provided help
        action_index[name].call = (*function);	// Sets the action's function to call to the provided function
    }

    // Constructor
	Console()
	{
		finished = 0; // Prepares for reading cycle.
        action_new("quit","Quits this application",quit);
		action_new("help","Brings this list",help);
	}
};

int thing()
{
    cout << "Who called thing?" << endl;
    return 0;
}

int main()
{
	Console keyholder;
	keyholder.action_new("thing","Just a damn thing.",thing);
	keyholder.read();
	return 0;
}


This code works perfectly if you comment the "action_new(...)" in the Console class constructor.

wolih
Newbie Poster
8 posts since Feb 2008
Reputation Points: 10
Solved Threads: 0
 

http://www.newty.de/fpt/index.html
Pointers to member functions need extra syntax.

> action_index[name].call = (*function);
If you're just storing it (it looks like you're trying to call it), it would be
action_index[name].call = function;

Salem
Posting Sage
Team Colleague
11,531 posts since Dec 2005
Reputation Points: 5,862
Solved Threads: 953
 

Another way to correct situation: make help(), quit(), finished and action_index members static.
In that case you can add pointers to help and quit functions to action_index map. Pointers to static member functions are the same as usual pointers.

ArkM
Postaholic
2,001 posts since Jul 2008
Reputation Points: 1,234
Solved Threads: 348
 

consider using the std::tr1 polymorphic function wrappers. this would allow using free functions, member functions and function objects in a polymorphic way.

if your compiler does not ship with tr1, you can use boost::function in the interim.
http://www.boost.org/doc/libs/1_36_0/doc/html/function/tutorial.html#id2903300

#include <iostream>
#include <string>
#include <map>
#include <vector>

// tr1: #include <functional>
#include <boost/function.hpp>

using std::map;
using std::string;
using std::vector;
using std::cout;
using std::cin;
using std::endl;

class Console
{
	// Private variables
  int finished, success;
  string input;

public:
	// The Base structure of the console and resposible for automation.

  // tr1: typedef std::tr1::function< int(Console*) > function_type ; 
  typedef boost::function< int(Console*) > function_type ;
  struct Action
  {
    string help;     		// Action documentation
    function_type call;	// Function to call
  };
  map<string,Action> action_index;

  // Functions
  int quit()
  {
    finished = 1;
    return 0;
  }

  void report_error(string error_kind)
  {
    if (error_kind == "com")
    {
      cout << "Invalid command. Type \"help\" for a list of commands." << endl;
    }
  }

  int help()
  {
   	cout << "Action:\t\t\tDescription:" << endl;
  	// For each element in the action_list, print it's name and description
   	for (map<string,Action>::iterator counter = action_index.begin(); counter != action_index.end(); counter++)	
   	{
   		cout
    		// Print command's name
					<< counter->first
					<< "\t\t\t"
    		// Print command's description
					<< counter->second.help
					<< endl;
   	}
    	return 0;
   }

	void read()
	{
		// Asks for input, and reads it
		while (finished != 1)
		{
			success = 0;
			cout << ">>>"; getline(cin,input);
			for (map<string,Action>::iterator counter = action_index.begin(); counter != action_index.end(); counter++)
			{
				if (input == counter->first)
				{
					success = 1;
					counter->second.call(this);
					break;
				}
			}
			if (!success) report_error("com");
		}
	}

	// Action creator
    void action_new( string name, string help, function_type function )
    {
        action_index[name].help = help;	 // Sets action's help string to the provided help
        action_index[name].call = function; // Sets the action's function to call to the provided function
    }

    // Constructor
	Console()
	{
	  finished = 0; // Prepares for reading cycle.
          action_new("quit","Quits this application",&Console::quit);
          action_new("help","Brings this list",&Console::help);
	}
};

int main()
{
	Console keyholder;
	keyholder.read();
}


using std::tr1::bind (or boost::bind) would make things even more flexible. http://www.boost.org/doc/libs/1_36_0/libs/bind/bind.html#with_boost_function

vijayan121
Posting Virtuoso
1,606 posts since Dec 2006
Reputation Points: 1,159
Solved Threads: 287
 

Well... I have now fixed the problem in a very arbitrary way...
I removed the quit function from the Console class, because--what if somebody wanted to have a custom quit? I just made finished a global bool.

About help, I set it as built in into the action_index thing, so i have no need to add it in the constructor. I have changed the file a lot, and you can download the complete package of source code in:
http://ubuntuforums.org/showthread.php?p=5821558#post5821558

wolih
Newbie Poster
8 posts since Feb 2008
Reputation Points: 10
Solved Threads: 0
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You