How to pass function pointer by reference?

Discussion in 'C++' started by Immortal Nephi, May 27, 2009.

  1. 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;
    }
    Immortal Nephi, May 27, 2009
    #1
    1. Advertising

  2. On May 27, 6:25 pm, Stuart Golodetz
    <> wrote:
    > 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
    >         }
    >
    > };


    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 -
    Immortal Nephi, May 28, 2009
    #2
    1. Advertising

  3. Immortal Nephi

    SG Guest

    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
    SG, May 28, 2009
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mr A
    Replies:
    111
    Views:
    2,075
  2. Robert
    Replies:
    10
    Views:
    1,359
    E. Robert Tisdale
    Aug 24, 2005
  3. LuB
    Replies:
    6
    Views:
    445
    Mike Wahler
    Sep 23, 2005
  4. Louis
    Replies:
    7
    Views:
    771
    Michael Tsang
    Oct 1, 2009
  5. A
    Replies:
    7
    Views:
    626
Loading...

Share This Page