Pointer to member function

G

Gernot Frisch

class A
{
A(int mode) {pF = F1;}
void F1() {}
void (*pF)();
};

How do I do something like this?

I need a function that depends on variable 'mode' and will be called
very very often. Thus, implementing a "if (mode)" in the function is
not possible.

The function returns a pointer to a screen pixel and determines
landscape/portrait mode.
 
G

Gianni Mariani

Gernot said:
class A
{
A(int mode) {pF = F1;}
void F1() {}
void (*pF)();
};

How do I do something like this?

I need a function that depends on variable 'mode' and will be called
very very often. Thus, implementing a "if (mode)" in the function is
not possible.

The function returns a pointer to a screen pixel and determines
landscape/portrait mode.

I'm not exactly sure what you're doing.

How about this (using pointer to member syntax).

class A
{
public:
void F1();
void F2();

void F( void ( A::* func )() )
{
(this->*func)();
}
};

int main()
{
A a;

a.F( & A::F1 );
a.F( & A::F2 );
}
 
P

Pete Becker

Gernot said:
I need a function that depends on variable 'mode' and will be called
very very often. Thus, implementing a "if (mode)" in the function is
not possible.

Be careful here: the code for calling through a pointer to member
function can be quite complex. Try it before you optimize it.
 
D

Dietmar Kuehl

Gernot said:
class A
{
A(int mode) {pF = F1;}
void F1() {}
void (*pF)();
};

How do I do something like this?

Read the FAQ, specifically the section on pointer-to-members.
I need a function that depends on variable 'mode' and will be called
very very often. Thus, implementing a "if (mode)" in the function is
not possible.

You mean, you want to exchange the if-statement with an approach
which is even slower? Pointer to [member] functions are the way to
go! You would trade one or two CPU cyles of the if-statement plus
an occasional pipeline stall (when you change between modes the
branch prediction will be confused) against a full blown function
call. The function call will need to put parameters into appriate
registers and possibly save and later restore other registers.

If you really want to avoid the overhead, you might want to use
a template for your code which is parameterized e.g. with pointer
to members selecting the appropriate member variable. In any case,
I doubt that you will get better performance using a pointer to
[member] function than the if-statement if you have just two
choices.
 
G

Gianni Mariani

Michael said:
Why are there the &s?

Because it's an error otherwise. When converting to "pointer to member"
funtion, the "&" is required. This is not so for non-member funtions.
 
G

Gernot Frisch

Dietmar Kuehl said:
Gernot said:
class A
{
A(int mode) {pF = F1;}
void F1() {}
void (*pF)();
};

How do I do something like this?

Read the FAQ, specifically the section on pointer-to-members.
I need a function that depends on variable 'mode' and will be
called
very very often. Thus, implementing a "if (mode)" in the function
is
not possible.

You mean, you want to exchange the if-statement with an approach
which is even slower? Pointer to [member] functions are the way to
go! You would trade one or two CPU cyles of the if-statement plus
an occasional pipeline stall (when you change between modes the
branch prediction will be confused) against a full blown function
call. The function call will need to put parameters into appriate
registers and possibly save and later restore other registers.

If you really want to avoid the overhead, you might want to use
a template for your code which is parameterized e.g. with pointer
to members selecting the appropriate member variable. In any case,
I doubt that you will get better performance using a pointer to
[member] function than the if-statement if you have just two
choices.

OK. What's the fastest way of doing:

void MyBMPClass::Draw()
{
for (x ...)
for (y ...)

switch(mode)
{
case 0:
Func0(x,y);
break;
case 1:
Func1(x,y);
break;
...
}
}
 
M

Michael Etscheid

Gernot said:
OK. What's the fastest way of doing:

void MyBMPClass::Draw()
{
for (x ...)
for (y ...)

switch(mode)
{
case 0:
Func0(x,y);
break;
case 1:
Func1(x,y);
break;
...
}
}

It might be this:

typedef void (*fp)(int, int);
fp arr[100] = { Func0, Func1, ... Func99 };

void MyBMPClass:Draw()
{
arr[mode];
}
 
M

Michael Etscheid

Gernot said:
OK. What's the fastest way of doing:

void MyBMPClass::Draw()
{
for (x ...)
for (y ...)

switch(mode)
{
case 0:
Func0(x,y);
break;
case 1:
Func1(x,y);
break;
...
}
}

It might be this:

typedef void (*fp)(int, int);
fp arr[100] = { Func0, Func1, ... Func99 };

void MyBMPClass::Draw()
{
// create x and y

arr[mode](x, y);
}
 
D

Dietmar Kuehl

Gernot said:
OK. What's the fastest way of doing:

void MyBMPClass::Draw()
{
for (x ...)
for (y ...)

switch(mode)

I assume that 'mode' is a constant within 'Draw()' and that speed
is your ultimate goal, i.e. you would accept a reasonable increase
in code size. The approach using a switch statement within the
inner loop is probably better than using a function pointer due to
the function call overhead (as noted in my previous article or by
Pete Becker). If 'mode' is indeed constant within your function,
you would get still better performance using something like

switch (mode)
{
case 0:
for (x ...)
for (y ...)
Func0(x, y);
break;
case 1:
for (x ...)
for (y ...)
Func1(x, y);
break;
...
}

Of course, you typically don't want to repeat the code, especially
if it is even more than just the two nested loops. In this case,
you might try to do it like this:


template <void (*func)(int, int)>
void DrawAux()
{
for (x ...)
for (y ...)
func(x, y);
}

void Draw(int mode)
{
switch (mode)
{
case 0: DrawAux<Func0>(); break;
case 1: DrawAux<Func1>(); break;
...
}
}

Whether the compiler optimizes this code to avoid the function call
is, of course, depending on the compiler. You will need to profile
this.

BTW, rather than using a switch statement in the above, you might
also try to use a virtual function: the virtual function dispatch
in the inner loop may be too expensive but putting the loop into
the function may well warrant the virtual function.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,738
Latest member
JinaMacvit

Latest Threads

Top