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.

Recommended Answers

All 4 Replies

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.

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

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

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.