Usage of reinterpret_cast (Help)

Hello cplusplus.com community!

I have just started with C++ game development using C++ and is currently trying to make some kind of script system for my game.

So far ive searched around on the internet looking for a way to do this and it boils down to either using lua or pure C++.

Im currently trying the C++ way but have problems using a function called "reinterpret_cast"

I found a snippet of code on SO (http://stackoverflow.com/questions/2136998/using-a-stl-map-of-function-pointers) and it works fine if i implement it the way said here. The diffrence is that i want to use it in my own class and be able to call functions via a map from that specific class.

My code so far is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Ball{
public:
	Ball::Ball(){

		// Add it to your map
		std::map<std::string, void (Ball::*)()> any_map;
		any_map["A"] = anotherFunction;
		any_map["B"] = yetAnotherFunction;

	        // Call the function
		reinterpret_cast<void(*)()>(any_map["B"])();
	};

	void anotherFunction(){
		std::cout << "Another function called" << std::endl;
	}

	void yetAnotherFunction(){
		std::cout << "Yet another function called" << std::endl;
	}

};


Where "reinterpret_cast<float(*)(int x)>(any_map["B"])(5);" is the line thats failing, How would this line be in order to call functions from my map?

All help is welcome!

Thanks alot!
Driiper
Last edited on
Why are you trying to do that reinterpret_cast in the first place? You trying to cast a member function pointer into a pointer to a function taking an int and returning a float, and then call it. Does that make sense to try and call anotherFunction or yetAnotherFunction as if they took an int and returned a float?
I edited some of my post.

I have sadly no idea what i'm doing. what i want is to call those functions from my map. And from reading on SO i was directed to using reinterpret_cast. Do you have any suggestion on how i can accomplish what i want without using it?

Edit:
The reason i had float there was after trying it in my main method, which worked perfectly:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int FuncA()
{
	return 1;
}

float FuncB(int x)
{
	std::cout << x << std::endl;
	return x;
}

int main(){
		// Add it to your map
		std::map<std::string, void(*)> any_map;
		any_map["A"] = FuncA;
		any_map["B"] = FuncB;

		// Call the function
		float test = reinterpret_cast<float(*)(int x )>(any_map["B"])(6);
		std::cout << test << std::endl;

}


So the problem is to use it in my "Ball" class

Thanks
Driiper
Last edited on
You should use std::function for the mapped value.

You should always know beforehand what the parameters and return values are, so there's no reason to ever cast anything.
In order to call a member function (even through a pointer), you need to supply a 'this' pointer so it knows which object to act on.

1
2
3
any_map["A"] = &Ball::anotherFunction; // <- proper way to get a pointer to the function

(this->*any_map["A"])();  // <- proper way to call it (the parenthesis are necessary) 


Of course C++ member function pointers are a syntax nightmare, so LB is right, using std::function would be easier:

1
2
3
4
5
std::map<std::string, std::function<void()>> any_map;

any_map["A"] = std::bind(&Ball::anotherFunction,this); // get pointer

any_map["A"]();  // <- call it 



EDIT:

And yeah... you should avoid reinterpret_cast unless you are absolutely certain you know all the implications of the cast. Using reinterpret_cast to get around a compiler error is basically telling the compiler:

"Shut up, I know what I'm doing, and I know it's OK, so don't bother checking it for me."


In this case, you don't fully understand the implications of casting these function pointers (you have return type mismatches, you are missing 'this' pointers, etc), so telling the compiler to "shut up" with a reinterpret_cast is very dangerous.
Last edited on
I found a snippet of code on SO (http://stackoverflow.com/questions/2136998/using-a-stl-map-of-function-pointers)

You can tell that's a very low-quality answer by void main. It's undefined implementation-defined (didn't see what's happening right away) behavior to do what it is doing even if it appears to "work fine". It also doesn't compile on compliant compilers (no implicit cast from function type to pointer to void)
Last edited on
I think i understand what you guys, mean and i thank alot for all of the great answers you have given me. Using std::function seems to work like a charm!

again Thanks!


Kind Regards
Driiper
Hey again,

Was wondering if its possible to use parameters in my functions (may be different amount of parameters in each of the functions)

Currently i'm trying to do this with Disch's method to call a method (works flawlessy without parameters)

1
2
3
4
5
6
		std::map<std::string, std::function<void()>> any_map;
		
		
		any_map["A"] = std::bind(&Ball::move,this); // get pointer
		any_map["A"](5);  // <- call it 


Where the function looks like this:

1
2
3
4
	void move(int x ){

		std::cout << "Another function called" <<  x << std::endl;
	}



Thanks alot!

Driiper
Was wondering if its possible to use parameters in my functions (may be different amount of parameters in each of the functions)


Yes this is possible, though I would question your design if differing parameters is really necessary.


There are 2 function signatures with std::function:
1) The signature of the function being called (ie: what you have a pointer to)
2) The signature of the std::function itself (ie: how you call it)

std::bind ties the two together.

In my previous example:

1
2
3
4
5
6
std::function<void()> f;  // <- void() is std::function's signature
   // meaning this function can be called with no parameters and returns void

// however... Ball::anotherFunction takes a hidden 'this' parameter, so it doesn't
// quite match that signature.  Therefore we need to use bind:
f = std::bind( &Ball::anotherFunction, this );


The first parameter to bind is the pointer to the function we're calling... and then the parameters after it are the params passed to that function. The first of which is the hidden 'this' parameter (if the object is a member function).

In your case, you want to change std::function's signature to void(int) so you can pass a single int as a parameter:

1
2
3
4
5
std::function<void(int)> f;

f = std::bind( &Ball::move, this, std::placeholders::_1 );

f(5);  // calls this->move(5); 


Here, bind passes 'this' as the hidden 'this' param for the function... and it
uses a 'placeholder' meaning "whatever you pass to the std::function when you call it". Since we call f(5);, 5 is used as placeholders::_1, which is passed as the next parameter to Ball::move.

If the function has a different signature, you just have to fill in the params as necessary when you bind it.

1
2
3
4
5
6
7
8
9
10
11
12
void Ball::Move2(int x, int y) { ... }

std::function<void(int)> f;
f = std::bind(  &Ball::Move2, this, std::placeholders::_1, 0 );

f(3);  // calls this->Move2( 3, 0 );

f = std::bind(  &Ball::Move2, this, 5, std::placeholders::_1 );

f(2);  // calls this->Move2( 5, 2 );

//etc 
Last edited on
Hi and Thanks!

This way could work but it may be a overcomplicated way to handle my main problem. (If its a ok way of doing it ill use this method though).

My plan was to use this as a way of "scripting" some parts of my game.
I was thinking of having a file reading line by line and with that call different function my ball is supposed execute.

Example:
1
2
3
4
5
6
7
8
move(5,20)
spin(50,20,10)
accellerate(10)
move(5,20)
wait(50)
move(10,30)

...etc


and with this i would have "ok" scripting system for my game.

Would this way be a bad way of handling my problem? Should i use somthing else to get this kind of behaviour in my application?

Thanks
Driiper
If you're only calling functions, you could use an expression evaluation library and just add the functions to it. No need to reinvent the wheel ;)
Hello,

Do you have a specific library you can recommend?


Thanks
Driiper
muParser is pretty good, and I know for a fact it can do this.

i will take a look at it,

Thanks alot!

Driiper
Topic archived. No new replies allowed.