Skip to main content
GameDev.net gamedev.net
🔒 Locked

map/multimap function_pointer-vector woes

Started by bc Oct 12, 2005 at 10:09 AM 4 replies 650+ views
Original Post
bc
bc
Howdy! I'm about 3 weeks into my adventure with C++ and I'm already onto advanced topics like function pointers :) Go me! I'm starting to think they're a little too advanced though, because I'm still having trouble doing what I want. Ideally I'd like to have a multimap of function pointers->vector of strings, but if I can at least get a map of vectors->function pointers I'll be happy (for now). I think the problems are related to the same misunderstanding I have about function pointers and maps though. Okay, here's some snippets of code. Help me out and enlighten me if you can! Defining the map:

typedef bool(*action_handler_func)( const vector_string_t * );
typedef multimap< action_handler_func, vector_string_t > map_func_to_vector_string_t;

class Action
{
public:
        static bool action_scroll_list  (const vector_string_t *v);
	map_func_to_vector_string_t   action;
....
Inside of a static member function of the Action class:

bool Action::build_actions_callback(const boost::match_results<std::string::const_iterator>& in)
{
	vector_string_t v;
	v = explode(in.str(2), ",");
	string s = in.str(1);
	if (s == "SCROLL_LIST")
	{
                /*
                   Errors on the next line with:

                   error C2676: binary '[': 'map_func_to_vector_string_t' does
                   not define this operator or a conversion to a type
                   acceptable to the predefined operator
                 */
		me->action[(&action_scroll_list)] = v;
	}
The action_scroll_list function looks like this:

bool Action::action_scroll_list  (const vector_string_t *v)
{
	return true;
}
I've tried a bunch of variations on this, like creating a string->function_pointer map, a vector of function pointers, and a map of function_pointers->string and nothing seems to work. They all error with the same error message, whenever I try and assign a function pointer. What am I missing? --Steve
dimebolt
dimebolt
It might help if you'd post what you actually want to achieve with this. It seems odd to have function pointers as index into a map (or vector for that matter).

Also, post the error messages or behaviour you're getting.
EDIT: sorry, the error is there, I should read better

Tom
bc
bc
Okay, well, I'm building a GUI system of sorts. In the config file you'd be able to specify a bunch of actions you'd like to do, scrolling the list, flipping an image, and so on.

Instead of building a giant if/else if block that would get processed every time you pressed a key, my idea was that it would be much mor efficient to build a list of function pointers at run-time so the appropriate functions would just get called automatically with (pseudo code):

map_func_to_vector_string_t::iterator k;k->first(&k->second);


instead of:
map_func_to_vector_string_t::iterator k;if (k->first == "SCROLL_LIST"){    scroll_list(&k->second);}else if (k->first == "FLIP_IMAGE"){    flip_image(&k->second);}....


Ya see what I mean? Is there a "better" way of doing it than with my function pointer deal?

--Steve
dimebolt
dimebolt
Well, I'm still a bit confused about the purpose, but I think I found your problem. There are two actually. First, you shouln't use the & as action_scroll_list itself is already a function pointer. Instead use:
me->action[action_scroll_list] = v;


Second, it doesn't seem multimap has a proper [] operator defined that works like you use it. I lack experience with it multimaps, but when thinking about it, the [] operator makes no sense on a multimap as there is no single value to return. Therefore, this operator[] construction will work only for a map. If you really need a multimap, you can use:
me->action.find(action_scroll_list)

Which returns a multimap iterator for the entry you want.

Tom
jdhardy
jdhardy
Quote:
Original post by dimebolt
Which returns a multimap iterator for the entry you want.
Slight correction: it returns an entry. Use the equal_range() member of function multimap to get all matching entries.

Of course, indexing a map with function pointers doesn't make much sense to me. Why not:
typedef void (*func_t)();    //I may have the syntax wrongtypedef map<string, func_t> callbacks;//... add the callbacks ...// Find the appropriate callback and call it.callbacks::iterator it = callbacks.find("some_action");if(it != callbacks.end())    it->second();    //call the function with no arguments


If the arguments are always the same (which is a good idea when working with callbacks), just add the appropriate arguments to the function and be sure to pass them when it is called.

For functions that take differing arguments, look at Boost.Function and Boost.Bind. Those are much more advanced, but much more flexible.
stylin
stylin
Quote:
Original post by jdhardy
... *** Source Snippet Removed *** ...

You're using your typedef as an object, and you should probably handle the invalid function case.
#include <iostream>#include <string>#include <map>void a( const std::string & s ) { std::cout << s << std::endl; }void b( const std::string & s ) { std::cout << s << std::endl; }void c( const std::string & s ) { std::cout << s << std::endl; }int main() {   typedef std::map< std::string, void (*)( const std::string & ) > callback_map;   callback_map callbacks;      // add callback functions   callbacks[ "function a" ] = &a   callbacks[ "function b" ] = &b   callbacks[ "function c" ] = &c   // execute the callback function   callback_map::iterator it = callbacks.find( "function b" );   if( it == callbacks.end() ) {      std::cerr << "Invalid callback specified" << std::endl;      return -1;   }   it->second( it->first );      return 0;}


[Edited by - stylin on October 12, 2005 4:50:09 PM]
:stylin: "Make games, not war." "...if you're doing this to learn then just study a modern C++ compiler's implementation." -snk_kid

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.