Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to pass function pointer by reference?

0 views
Skip to first unread message

Immortal Nephi

unread,
May 27, 2009, 6:32:05 PM5/27/09
to
I need to pass function pointer by reference because it invokes first
function and then invokes second function with the same parameter.
How can I fix it?

class A
{
public:
A() : m_a( 5 ) {}
~A() {}

void Run( void (&rF)( const A &ra ) )
{
printf("Run\n");
rF( *this ); // OK
Go1( rF( *this ) ); // Error
}

void Go1( void (&rF)( const A &ra ) )
{
printf("Go1\n");
Go2( ? ); // Fix
}

void Go2( void (&rF)( const A &ra ) )
{
printf("Go2\n");
rF( *this ); // OK
}
};

void F1( const A &ra )
{
printf("Test: %d\n", ra.m_a );
}

int main()
{
A a;
a.Run( F1 );

return 0;
}

Stuart Golodetz

unread,
May 27, 2009, 7:25:00 PM5/27/09
to
Immortal Nephi wrote:
> I need to pass function pointer by reference because it invokes first
> function and then invokes second function with the same parameter.
> How can I fix it?
>
> class A
> {
> public:
> A() : m_a( 5 ) {}
> ~A() {}
>
> void Run( void (&rF)( const A &ra ) )
> {
> printf("Run\n");
> rF( *this ); // OK
> Go1( rF( *this ) ); // Error
> }

The expression rF(*this) has type void: you're trying to pass the
non-existent result of a function with void return type to a function
which takes a void (&)(const A&). Replace rF(*this) with rF and it works
fine:

#include <cstdio>

class A
{
public:
int m_a;

A() : m_a( 5 ) {}

void Run( void (&rF)( const A &ra ) )
{
printf("Run\n");
rF( *this ); // OK

Go1( rF);
}

void Go1( void (&rF)( const A &ra ) )
{
printf("Go1\n");

Go2( rF );
}

void Go2( void (&rF)( const A &ra ) )
{
printf("Go2\n");
rF( *this ); // OK
}
};

void F1( const A &ra )
{
printf("Test: %d\n", ra.m_a );
}

int main()
{
A a;
a.Run( F1 );

return 0;
}

Note that you also needed to add a member variable m_a.

Regards,
Stu

Immortal Nephi

unread,
May 27, 2009, 10:09:36 PM5/27/09
to
On May 27, 6:25 pm, Stuart Golodetz

Thank you for the reply. It does work because F!() is global
function. What if you want to invoke member function like this below.

void B::F1( const A &ra )
void C::F1( const A &ra )

Pass Member Function by Reference will only work one object if
you use B object or C object.

> void Run( void (&rF)( const A &ra ) )

I am not sure how you can do this Run() function above. I
need to put B::F1 or C::F1 in a.Run( ?? ). C++ Compiler should
compile successfully if only one object is used however template
function is the answer to accept either B object or C object. I am
concerned. After you create static library or DLL library, C++
Compiler will fail to compile because it does not know which type in
template function.

Nephi

>
> void F1( const A &ra )
> {
>         printf("Test: %d\n", ra.m_a );
>
> }
>
> int main()
> {
>         A a;
>         a.Run( F1 );
>
>         return 0;
>
> }
>
> Note that you also needed to add a member variable m_a.
>
> Regards,
> Stu
>
>
>
>
>
> >    void Go1( void (&rF)( const A &ra ) )
> >    {
> >            printf("Go1\n");
> >            Go2( ? ); // Fix
> >    }
>
> >    void Go2( void (&rF)( const A &ra ) )
> >    {
> >            printf("Go2\n");
> >            rF( *this ); // OK
> >    }
> > };
>
> > void F1( const A &ra )
> > {
> >    printf("Test: %d\n", ra.m_a );
> > }
>
> > int main()
> > {
> >    A a;
> >    a.Run( F1 );
>
> >    return 0;

> > }- Hide quoted text -
>
> - Show quoted text -- Hide quoted text -
>
> - Show quoted text -

SG

unread,
May 28, 2009, 4:56:25 AM5/28/09
to
On 28 Mai, 04:09, Immortal Nephi wrote:
> [...] What if you want to invoke member function like this below.

>
> void B::F1( const A &ra )
> void C::F1( const A &ra )
>
>   Pass Member Function by Reference will only work one object if
> you use B object or C object.

This sounds familiar. Isn't it practically the same question you asked
in a previous thread? And didn't you already get an answer there?

You want to write non-templated function in your library that takes a
"call back" as parameter of some type that should support calling non-
static member functions of some bound object of various classes.

A type-safe variant is possible (via something like boost::function)
but you probably have to make sure that both, your library and the
client's code, is compiled with the same version of boost::function
(or whatever replacement you use). So, the binary interface is a bit
fragile.

The other option (the C way of doing this) would be to use a plain
function pointer in combination with a void pointer that stores some
user-defined address:

// non-templated library function
void run( void(*pf)(void*), void* context )
{
pf(context);
}

class C {
void f();
};

void invoke_C_f(void* ctx) {
static_cast<C*>(ctx)->f();
}

int main() {
C c;
run(&invoke_C_f,&c);
}

You just need to be careful with the pointer types. Here, C* is
converted implicitly to void* and back again to C* which is guaranteed
to be lossless. But the type information is lost with void* which is
why you can't rely on the conversion C* -> void* -> D* (where D is a
base class of C) to give you the same result as C* -> D*. The latter
conversion might include an automatic pointer adjustment.

Cheers!
SG

0 new messages