473,395 Members | 1,656 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Problem with std::map of function pointers

Hi there everyone,
I'm creating a very simple immediate mode command interpreter.
The final purpose is to provide a pluggable control and command
console for a MUD server I have written.

The basic theory is we wrap the functions we want exposed to the
console in a function with a prototype of

int func(State*)

the State* is an object that contains both
args, and results as std::vector<std::string>

Next we tie the wrapped functions up with a
std::map<std::string,Func*>

So that we can call the functions by name.

The problem I'm presently having is coming from the compiler, and
reads...
console.h:39: error: expected constructor, destructor, or type
conversion before '=' token

Line 39 reads...
FunctionList["print"] = &print;

That should be perfectly legal since my relevant code looks like...

typedef int(*Func)(const State&);
typedef std::map<std::string, Func*FL;
FL FunctionList;

int print(State& state){
for(int count = 0; count < state.argc(); count++){
std::cout << state.args[count];
}
return 0;
}
FunctionList["print"] = &print;

I have googled, and searched through years of newsgroup postings and
I'm not finding anything that might be causing this problem.
I'm hoping someone can help.

Below is a full code listing, it's only 56 lines including includes
and comments, so I'm hoping no one minds me posting it, my hope is
that someone can point out something I've missed.

Thanks in advance for the help!

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

class State{

public:
std::vector<std::string>
args,//Argument List
result; //Final Result

~State(){
while(args.size() != 0){
args.pop_back();
}

while(result.size() != 0){
result.pop_back();
}
}

inline int argc(){return(args.size());}
};

typedef int(*Func)(const State&);

typedef std::map<std::string, Func*FL;
typedef std::map<std::string, Func*>::value_type MapItem;
FL FunctionList;

int print(State& state){
for(int count = 0; count < state.argc(); count++){
std::cout << state.args[count];
}
return 0;
}

FunctionList["print"] = &print;

int execute(Func* func,std::vector<std::string>& args){
State state;
state.args.swap(args);
(*func)(state);
}

int parse(std::vector<std::string>& input){
FL::iterator iter = FunctionList.find(input.at(0));
if(iter != FunctionList.end()){
Func* func = iter->second;
execute(func,input);
}else{
std::cout << "Error: Command " << input.at(0) << " was not found!"
<< std::endl;
}
}

Feb 25 '07 #1
7 6239
DevNull wrote:
Hi there everyone,
I'm creating a very simple immediate mode command interpreter.
The final purpose is to provide a pluggable control and command
console for a MUD server I have written.

The basic theory is we wrap the functions we want exposed to the
console in a function with a prototype of

int func(State*)

the State* is an object that contains both
args, and results as std::vector<std::string>

Next we tie the wrapped functions up with a
std::map<std::string,Func*>

So that we can call the functions by name.

The problem I'm presently having is coming from the compiler, and
reads...
console.h:39: error: expected constructor, destructor, or type
conversion before '=' token

Line 39 reads...
FunctionList["print"] = &print;

That should be perfectly legal since my relevant code looks like...

typedef int(*Func)(const State&);
typedef std::map<std::string, Func*FL;
FL FunctionList;

int print(State& state){
for(int count = 0; count < state.argc(); count++){
std::cout << state.args[count];
}
return 0;
}
FunctionList["print"] = &print;

I have googled, and searched through years of newsgroup postings and
I'm not finding anything that might be causing this problem.
I'm hoping someone can help.

Below is a full code listing, it's only 56 lines including includes
and comments, so I'm hoping no one minds me posting it, my hope is
that someone can point out something I've missed.

Thanks in advance for the help!

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

class State{

public:
std::vector<std::string>
args,//Argument List
result; //Final Result

~State(){
while(args.size() != 0){
args.pop_back();
}

while(result.size() != 0){
result.pop_back();
}
}

inline int argc(){return(args.size());}
};

typedef int(*Func)(const State&);

typedef std::map<std::string, Func*FL;
typedef std::map<std::string, Func*>::value_type MapItem;
FL FunctionList;

int print(State& state){
for(int count = 0; count < state.argc(); count++){
std::cout << state.args[count];
}
return 0;
}

FunctionList["print"] = &print;

int execute(Func* func,std::vector<std::string>& args){
State state;
state.args.swap(args);
(*func)(state);
}

int parse(std::vector<std::string>& input){
FL::iterator iter = FunctionList.find(input.at(0));
if(iter != FunctionList.end()){
Func* func = iter->second;
execute(func,input);
}else{
std::cout << "Error: Command " << input.at(0) << " was not found!"
<< std::endl;
}
}
It's simple enough, assignments are not allowed at global scope. You
must put all assignments in a function.

int main()
{
FunctionList["print"] = &print;
}

should compile.

john
Feb 25 '07 #2
On Feb 25, 4:28 am, John Harrison <john_androni...@hotmail.comwrote:
DevNull wrote:
Hi there everyone,
I'm creating a very simple immediate mode command interpreter.
The final purpose is to provide a pluggable control and command
console for a MUD server I have written.
The basic theory is we wrap the functions we want exposed to the
console in a function with a prototype of
int func(State*)
the State* is an object that contains both
args, and results as std::vector<std::string>
Next we tie the wrapped functions up with a
std::map<std::string,Func*>
So that we can call the functions by name.
The problem I'm presently having is coming from the compiler, and
reads...
console.h:39: error: expected constructor, destructor, or type
conversion before '=' token
Line 39 reads...
FunctionList["print"] = &print;
That should be perfectly legal since my relevant code looks like...
typedef int(*Func)(const State&);
typedef std::map<std::string, Func*FL;
FL FunctionList;
int print(State& state){
for(int count = 0; count < state.argc(); count++){
std::cout << state.args[count];
}
return 0;
}
FunctionList["print"] = &print;
I have googled, and searched through years of newsgroup postings and
I'm not finding anything that might be causing this problem.
I'm hoping someone can help.
Below is a full code listing, it's only 56 lines including includes
and comments, so I'm hoping no one minds me posting it, my hope is
that someone can point out something I've missed.
Thanks in advance for the help!
#include <iostream>
#include <vector>
#include <map>
class State{
public:
std::vector<std::string>
args,//Argument List
result; //Final Result
~State(){
while(args.size() != 0){
args.pop_back();
}
while(result.size() != 0){
result.pop_back();
}
}
inline int argc(){return(args.size());}
};
typedef int(*Func)(const State&);
typedef std::map<std::string, Func*FL;
typedef std::map<std::string, Func*>::value_type MapItem;
FL FunctionList;
int print(State& state){
for(int count = 0; count < state.argc(); count++){
std::cout << state.args[count];
}
return 0;
}
FunctionList["print"] = &print;
int execute(Func* func,std::vector<std::string>& args){
State state;
state.args.swap(args);
(*func)(state);
}
int parse(std::vector<std::string>& input){
FL::iterator iter = FunctionList.find(input.at(0));
if(iter != FunctionList.end()){
Func* func = iter->second;
execute(func,input);
}else{
std::cout << "Error: Command " << input.at(0) << " was not found!"
<< std::endl;
}
}

It's simple enough, assignments are not allowed at global scope. You
must put all assignments in a function.

int main()
{
FunctionList["print"] = &print;

}

should compile.

john
Wow thank you that did the trick!
Something like that you'ld think the compile would have a specific
message for.

Feb 25 '07 #3
On Feb 25, 1:28 pm, John Harrison
<john_androni...@hotmail.comwrote:
DevNull wrote:
I'm creating a very simple immediate mode command
interpreter. The final purpose is to provide a
pluggable control and command console for a MUD server
I have written.
The basic theory is we wrap the functions we want
exposed to the console in a function with a prototype
of
int func(State*)
the State* is an object that contains both
args, and results as std::vector<std::string>
Next we tie the wrapped functions up with a
std::map<std::string,Func*>
So that we can call the functions by name.
FunctionList["print"] = &print;

It's simple enough, assignments are not allowed at global
scope. You must put all assignments in a function.

int main()
{
FunctionList["print"] = &print;
}
There seem to be a number of other problems with the code.
typedef int(*Func)(const State&);
typedef std::map<std::string, Func*FL;
Are you sure you want to store pointers to pointers?
int print(State& state){
int print ( const State & state )
for(int count = 0; count < state.argc(); count++){
std::cout << state.args[count];
}
return 0;
}
FunctionList["print"] = &print;
Once you fix constness, & print will be a Func, but you're
trying to store Func * in your map, so this won't work
anyway.

--
roy axenov

Feb 25 '07 #4
On Feb 25, 4:45 am, "roy axenov" <r_axe...@mail.ruwrote:
On Feb 25, 1:28 pm, John Harrison

<john_androni...@hotmail.comwrote:
DevNull wrote:
I'm creating a very simple immediate mode command
interpreter. The final purpose is to provide a
pluggable control and command console for a MUD server
I have written.
The basic theory is we wrap the functions we want
exposed to the console in a function with a prototype
of
int func(State*)
the State* is an object that contains both
args, and results as std::vector<std::string>
Next we tie the wrapped functions up with a
std::map<std::string,Func*>
So that we can call the functions by name.
FunctionList["print"] = &print;
It's simple enough, assignments are not allowed at global
scope. You must put all assignments in a function.
int main()
{
FunctionList["print"] = &print;
}

There seem to be a number of other problems with the code.
typedef int(*Func)(const State&);
typedef std::map<std::string, Func*FL;

Are you sure you want to store pointers to pointers?
int print(State& state){

int print ( const State & state )
for(int count = 0; count < state.argc(); count++){
std::cout << state.args[count];
}
return 0;
}
FunctionList["print"] = &print;

Once you fix constness, & print will be a Func, but you're
trying to store Func * in your map, so this won't work
anyway.

--
roy axenov
Thank you, I have fixed those, they were typos.

Feb 25 '07 #5

"DevNull" <sm*****@gmail.comwrote in message
news:11**********************@v33g2000cwv.googlegr oups.com...
On Feb 25, 4:45 am, "roy axenov" <r_axe...@mail.ruwrote:
>On Feb 25, 1:28 pm, John Harrison
[SNIP]
Thank you, I have fixed those, they were typos.
Just as a general remark: you might consider making your function table a
static map, as you most probably need only one unique instance, and wrap in
a class which also takes take of initializing, function lookup etc. IMO this
would give you cleaner and more flexible design, but naturally that's a
personal opinion.

Cheers
Chris

Feb 25 '07 #6
On Feb 25, 7:43 am, "Chris Theis" <chris.theis@n o s p am.cern.ch>
wrote:
"DevNull" <smor...@gmail.comwrote in message

news:11**********************@v33g2000cwv.googlegr oups.com...
On Feb 25, 4:45 am, "roy axenov" <r_axe...@mail.ruwrote:
On Feb 25, 1:28 pm, John Harrison
[SNIP]
Thank you, I have fixed those, they were typos.

Just as a general remark: you might consider making your function table a
static map, as you most probably need only one unique instance, and wrap in
a class which also takes take of initializing, function lookup etc. IMO this
would give you cleaner and more flexible design, but naturally that's a
personal opinion.

Cheers
Chris
Done and thank you for the feedback!

Feb 26 '07 #7
On Feb 26, 12:37 pm, "DevNull" <smor...@gmail.comwrote:
On Feb 25, 7:43 am, "Chris Theis" <chris.theis@n o s p am.cern.ch>
wrote:
Just as a general remark: you might consider making your function table a
static map, as you most probably need only one unique instance, and wrap in
a class which also takes take of initializing, function lookup etc. IMO this
would give you cleaner and more flexible design, but naturally that's a
personal opinion.
Cheers
Chris

Done and thank you for the feedback!
You should also take a look at using functor like objects. They may be
easier to use and initialise. If you have a functor super-class that
places itself into the map on initialisation (and removes itself on
destruction) then your maintenance will be easier because you just
declare a single const object for each functor type.

Simplified pseudo-code something like this:

class Functor;
map< string, const Functor * g_functors;

class Functor {
protected:
Functor( string name ) {
g_functors[ name ] = this;
}
virtual ~Functor() {
}
public:
virtual void execute( State * ) = 0;
};
Now for each one you just do this:

const class Print : class Functor {
public:
Print() : Functor( "print" ) {}
void execute( State * ) const {
// Whatever it does
}
} c_print;

This saves you from adding a function and remembering to add it to the
map as that is done automatically.

It also makes it easy to extend as you can just dynamically load
additional code at the time of executions (i.e. on Windows use
LoadLibrary to fetch a new DLL, which can even be specified on the
command line - I'm sure there must be something similar on UNIX
variants) and all of the new functions in the new code will
automatically become available.

This solution is more decoupled that storing raw function pointers. It
also allows for the objects to be initialised in different ways to
configure closely related functions. I.e.:

const class Print : class Functor {
public:
Print( ostream &stream, string name ) : Functor( name ),
m_stream( ostream ) {}
void execute( State * ) const {
// Whatever it does
}
private:
std::ostream &m_ostream;
} c_print( std::out, "print" ), c_log( g_mylogstream, "log" );
K

Feb 26 '07 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Woodster | last post by:
I have declared the following std::map<std::string, std::string> myMap; to pass myMap to functions should I be declaring functions as: void function(std::map<std::string, std::string>); ...
25
by: Christopher Benson-Manica | last post by:
If you liked the functionality of std::map, but found that you couldn't trust your implementation to handle nonstandard data structures, how would you code a wrapper? I've produced the following:...
44
by: jmoy | last post by:
I am a C programmer graduating to C++. As an exercise I wrote a program to count the number of times that different words occur in a text file. Though a hash table might have been a better choice,...
14
by: Flzw | last post by:
Well I have a map like this : std::map <string, CObject> ObjectList; I have a function like this : CObject* NewObject( char* Name, CArg* Arg) { std::string key = Name; ObjectList =...
2
by: Serengeti | last post by:
Hello, in my class I have a map that translates strings to pointers to some member functions. The code goes like this: class F { typedef void (Function::*MathFuncPtr)(); std::map<std::string,...
1
by: Avery Fong | last post by:
The following program will result in a compile error when building under Debug but will compile under Release. Why does is work under Release mode but not under Debug This program is developed...
13
by: kamaraj80 | last post by:
Hi I am using the std:: map as following. typedef struct _SeatRowCols { long nSeatRow; unsigned char ucSeatLetter; }SeatRowCols; typedef struct _NetData
7
by: Matthias Pfeifer | last post by:
Hi there, a std::map is build from std::pair elements where for a pair p p.first is called the key and p.second the value. Is there a way to keep the map sorted by the values? Ie is there a...
3
by: digz | last post by:
This is a very simplified version of something I am trying to understand. The State object holds the strings and maps , and I pass a reference to State to the process Function which manipulates it...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.