Troubles optimizing some code:

Started by
4 comments, last by civguy 19 years, 5 months ago
Hello members, Is there a way to get a pointer to a member function of a class in C++? If not, why? I'm just sitting here, trying to optimize some code where a lot of accesses of the form [y*width+x] are made into an array. You can eliminate the multiplication when you replace them with shift operations. For a width of 640 that would be:

inline unsigned int shift640( unsigned int y )  { return (y<<9) + (y<<7); }

You can access your array now by using [shift640(y)+x] That is working well and is fast. Now I'm having the problem, I've got a image class where a function should be able to be used with any image size. So I thought I could store a pointer to the appropriate shift function, then in the loop just call the function in the pointer that I stored before. Something like that:

	// find a suitable shift function
	unsigned int (*funcShift)(unsigned int y);

	switch( width )
	{
	case 1920:	funcShift = blur_shift1920;		break;
	case 1600:	funcShift = blur_shift1600;		break;
	case 1280:	funcShift = blur_shift1280;		break;
	case 1200:	funcShift = blur_shift1200;		break;
	case 1152:	funcShift = blur_shift1152;		break;
	case 1080:	funcShift = blur_shift1080;		break;
	case 1024:	funcShift = blur_shift1024;		break;
	case 864:	funcShift = blur_shift864;		break;
	case 800:	funcShift = blur_shift800;		break;
	case 720:	funcShift = blur_shift720;		break;
	case 640:	funcShift = blur_shift640;		break;
	case 576:	funcShift = blur_shift576;		break;
	case 512:	funcShift = blur_shift512;		break;
	case 384:	funcShift = blur_shift384;		break;
	case 320:	funcShift = blur_shift320;		break;
	case 256:	funcShift = blur_shift256;		break;
	case 240:	funcShift = blur_shift240;		break;
	default:	funcShift = blur_shiftNoShift;	break;
	}

That's working well as long as the shift functions are not member functions of the image class itself. But they have to be, because the default function blur_shiftNoShift() needs to know the width of the image because the function returns just "y * m_width".

unsigned int blur_shiftNoShift( unsigned int y ){ return y * width; }

However, my compiler won't let me do that. And that's odd. Any hints? Thanks, Nils
_____________________________________http://www.winmaze.de, a 3D shoot em up in OpenGL, nice graphics, multiplayer, chat rooms, a nice community, worth visiting! ;)http://www.spheretris.tk, an upcoming Tetrisphere clone for windows, a 3D tetris game on a sphere with powerful graphics for Geforce FX and similar graphics cards.
Advertisement
Quote:Original post by Lyve
However, my compiler won't let me do that. And that's odd. Any hints?


Pointer to free-function != Pointer to member function

and in order to work with pointer to member functions you need an instance of the type in question.

[Edited by - snk_kid on November 23, 2004 5:36:43 AM]
Note that because you're accessing the function via a function pointer (which is a call you can't inline), you will likely kill any speed benifit you gained from using shifts instead of a generic multiplication in the first place.

Also note that you're probably prematurely optimizing, which is a BAD THING (tm). Code this optimized does not really belong in a userspace program. In drivers, yes.

All that said:

For the purpouses of explaining the syntax of C++, and how to make this example work (even if it's a bad idea to implement):

I'd suggest making the shift* functions static (prefered here, since it dosn't need to access any of the member functions). Example:

static unsigned int shift640( unsigned int y ) { return (y<<9) + (y<<7); }

(Note the lack of the inline keyword - it makes no sense in this context, since you're using a function pointer.)

Member functions of C++ classes are special, in that they work with an instance of the class - in other words they need a this pointer, which is used implicitly whenever you accesses a member of the class (other functions that use the this pointer, or directly through any non-static variables).

The use of the "static" keyword for a member function means you can't use the this pointer, or any non-static variables.

The use of the "static" keyword for a member variable means there's only one instance of that variable for the entire type. You'll also have to provide an instansiation of that variable in one of your compile units.

In cases where a "this" pointer is needed for the function to work, you need a different syntax. Example:

class MyClass{    int my_number;public:    MyClass( int my_number )        : my_number(my_number)    {    }    void print_number( void )    {        cout << "My number: " << my_number << endl;    }    void print_5_times_number( void )    {        cout << "My number times 5: " << (my_number * 5) << endl;    }};void (MyClass::*function)( void ); //Declares the pointerfunction = MyClass::print_number; //Sets the function calledMyClass my_class_5  ( 5);MyClass my_class_10 (10);my_class_5.*function(); //Prints 5my_class_10.*function(); //Prints 10function = MyClass::print_5_times_number;my_class_5.*function(); //Prints 25my_class_10.*function(); //Prints 50
if your wont to be able to use free-functions aswell as member functions to callback on then i would say use a combination of templates & generalized functors such as Boost.Function
Additionally, what you are proposing (an indirect function call) will be SLOWER on modern CPU:s than actually doing the multiplication in the normal way.
What I did in an old game was that I roofed the map width to closest power of 2. I.e. 500 => 512, 600 => 1024. Then used just one shift to access a row. This way you won't need separate functions for different image sizes, just one variable that tells how much to shift. But was it really worth it? Dunno, back then I didn't really profile...

This topic is closed to new replies.

Advertisement