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.
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;
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