Function Pointer as argument nightmare ('&' requires l-value)

Started by
22 comments, last by yacwroy 14 years, 7 months ago
As the title states, I'm getting a "'&' requires l-value" error from the following code:

void InitTitleScreen();

void CSystem::PlayMovie(const char *filename, void *func(void))
{
	//TODO: Play movie ....

         //Call the end-function at the end of the movie
	*func();
}

void CSystem::GameLoop()
{
	switch (g_nGameState)
	{
	case STATE_INITIALIZATION:
		{
			PlayMovie("data\\Intro.mov", &InitTitleScreen());
		}
		break;
	}
}

void InitTitleScreen()
{
	MessageBox(NULL, L"TEST", L"Function pointers suck...", MB_OK);
}
The line that is giving me the error is:

PlayMovie("data\\Intro.mov", &InitTitleScreen());
I've read and re-read tutorials on function pointers ... and can easily do it in C#, but I want to do it in C++ and it is just a little frustrating. The way I'm seeing it, &InitTitleScreen() is the address of InitTitleScreen(), and I pass that to the PlayMovie function, which then calls the function through the parameter. I know that the "l-value" thing means that there is no value to assign from that, but that doesn't make sense, because shouldn't the function have an address? I also tried doing the following:

void *FuncPtr = &InitTitleScreen
but that didn't help me much either ... just more errors...
Advertisement
Quote:Original post by jonathanplumb
The way I'm seeing it, &InitTitleScreen() is the address of InitTitleScreen()
InitTitleScreen() is not a function. InitTitleScreen() is a function call. InitTitleScreen is a function.
if I change the call to
PlayMovie("data\\Intro.mov", &InitTitleScreen);

I get the following:
error C2664: 'CSystem::PlayMovie' : cannot convert parameter 2 from 'void (__cdecl *)(void)' to 'void *(__cdecl *)(void)'
Try replacing "void *func(void)" with "void (*func)(void)"
Quote:Original post by Hodgman
Try replacing "void *func(void)" with "void (*func)(void)"
Actually, I'd recommend changing it to boost::function<void ()> - it's more readable (in my opinion) and it's more flexible, too!
I'm not sure what that "boost::" is, but I fixed it by doing the following:

Changed PlayMovie() to the following:
void CSystem::PlayMovie(const char *filename, void (*func)(void)){	//TODO: Play movie ....	(*func)();}


Changed GameLoop() to the following:
void CSystem::GameLoop(){	switch (g_nGameState)	{	case STATE_INITIALIZATION:		{			PlayMovie("data\\Intro.mov", &InitTitleScreen);		}		break;	}}


and InitTitleScreen() didn't change. I think it was just a problem with my parenthesis not in the right place, making some odd typecasts or something.

Thanks for the help. Now off to learn OpenGL --
Quote:Original post by jonathanplumb
I'm not sure what that "boost::" is, but I fixed it by doing the following:


boost is a great big bunch of C++ awesomeness. It's got a whole bunch of neat stuff, including smart pointer classes, cross-platform threading/synchronization, cross-platform file system classes, serialization, networking, regular expressions, and more. Certainly worth checking out.

Codeka was talking about boost::function which lets you create function objects for use as callbacks. You can also combine it with boost::bind to create callbacks to class member functions, which is really neat.
I know I'm late, but I bet that the reason you got the error is because you typed &InitScreen instead of InitScreen (when parenthesis are not used it becomes a pointer to the function).
Don't pay much attention to "the hedgehog" in my nick, it's just because "Sik" was already taken =/ By the way, Sik is pronounced like seek, not like sick.
Quote:Original post by jonathanplumb
void CSystem::PlayMovie(const char *filename, void (*func)(void)){	//TODO: Play movie ....	(*func)();}


Since you cannot pass functions as arguments (only function pointers), the asterisk in parameters is optional.

It is also optional when you call a function through a function pointer -- in fact, it is even more natural without the asterisk, because calling "normal functions" does a silent conversion to a function pointer first before calling the function anyway -- but that detail is not so important :)
void CSystem::PlayMovie(const char *filename, void func()){	//TODO: Play movie ....	func();}

This SHOULD work, but I haven't tested it. Please confirm.
I've testet it and it works well.

Anyway @OP you should really consider to take a look at boost.

This topic is closed to new replies.

Advertisement