From: Daniel Krügler on
On 4 Nov., 00:28, Ben <wudehui2...(a)gmail.com> wrote:
> Hi I need to associate a string with a function. I define the
> following table
>
> struct COMMAND {
> const WCHAR * name;
> void T::*proc(int);
> };

Please stay away from unnecessary names that complicate a
simple problem. For the following I assume that instead of
WCHAR you would have written char. Note also that

void T::*proc(int);

is no valid pointer to member function declaration. I assume
for the following that you meant

void (T::*proc)(int);

given some class type T.

> static const COMMAND commands[] = {
> {"north", fun0},
> {"east", fun1},
> {"south", fun2},
> {"west", fun3},
> };
>
> However I would like to have fun2 and fun3 corresponds to another type
> of function
> T::*proc(string)
>
> How can I do it?

To give a reasonable answer to that question it would be helpful
to understand how the *user* of commands should know
when (s)he has to call the array elements with an int argument
and when with a (std::)string(?) argument?

I would try to find an answer to this question first, because
it might point to a solution where

a) the caller of commands actually would prefer to provide no
explicit arguments at all. boost::bind would allow the creation
of such function wrappers including direct argument binding.

b) it shows that a single COMMAND[] is not what is needed,
but actually two (or more) arrays, e.g. by redefining COMMAND
as a template:

template<typename ArgType>
struct COMMAND {
const char* name;
void (T::*proc)(ArgType);
};

ending up in

static const COMMAND<int> int_commands[] = {
{"north", &T::fun0},
{"east", &T::fun1},
{"south", &T::fun2},
{"west", &T::fun3},
};

static const COMMAND<const std::string&> str_commands[] = {
{"right", &T::fun4},
{"left", &T::fun5},
{"up", &T::fun6},
{"down", &T::fun7},
};

HTH & Greetings from Bremen,

Daniel Kr�gler



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Nick Hounsome on
On 3 Nov, 23:28, Ben <wudehui2...(a)gmail.com> wrote:
> Hi I need to associate a string with a function. I define the
> following table
>
> struct COMMAND {
> const WCHAR * name;
> void T::*proc(int);
> };
>
> static const COMMAND commands[] = {
> {"north", fun0},
> {"east", fun1},
> {"south", fun2},
> {"west", fun3},
>
> };
>
> However I would like to have fun2 and fun3 corresponds to another type
> of function
> T::*proc(string)
>
> How can I do it?

How would you know what parameter (int or string) to supply to the
call?
If you answer this then we can suggest an appropriate answer.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Olivier on
you could eventually do it the following way :

#include <map>
#include <iostream>

template< typename Arg >
class command_list
{
public:
void register_command( char const *name, void (*cb)
( Arg ) )
{ command_map[name] = cb; }

void call( char const *name, Arg arg )
{ command_map[name](arg); }

private:
std::map<std::string, void (*)( Arg )> command_map;
};

class commands
: public command_list<std::string>
, public command_list<int>
{
public:
template< typename Arg >
void register_command( char const *name, void (*cb)
( Arg ) )
{ static_cast<command_list<Arg> &>(*this).register_command
(name, cb); }

template< typename Arg >
void operator()( char const *name, Arg arg )
{ static_cast<command_list<Arg> &>(*this).call(name,
arg); }
};

void north( int i ) { std::cerr << "in north( int i = " << i << " )
\n"; }
void south( std::string s ) { std::cerr << "in south( std::string
const &s = '" << s << "' )\n"; }
void east( std::string s ) { std::cerr << "in east( std::string
const &s = '" << s << "' )\n"; }
void west( int i ) { std::cerr << "in west( int i = " << i << " )
\n"; }

int main( )
{
commands cmds;

cmds.register_command("north", &north);
cmds.register_command("south", &south);
cmds.register_command("east", &east);
cmds.register_command("west", &west);

cmds("north", 0);
cmds("south", std::string("hello"));
cmds("east", std::string("again"));
cmds("west", 1);
}

This is a very simple implementation, and there are several points
you'll want to address :
- You most probably want to check for invalid names and duplicate
registered functions.
- Argument passing is not perfect as everything is passed by copy.
That can be fixed with a little template magic.
- You can't rely on implicit conversions to call commands.
- Changes can be made to the internals of 'command_list' to use a
static map.

--
Olivier


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]