C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Pointers to function and pointers to members

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Giulio Cespuglio
Guest





PostPosted: Tue Feb 24, 2004 3:30 am    Post subject: Pointers to function and pointers to members Reply with quote



Hi there,

I am dealing with a C library, in particular with a function that
takes a pointer to function. To keep it simple let's say

void libf( double(*fun)(double) )
{
fun( 3.0 );
}

I would like to know if it's possible to call this function with the
pointer to a member function of a specific object (i.e. with some
state associated to it). That is:

class A
{
public:
A( double d )
: m_d( d )
{
}

double f( double d )
{
return m_d * d;
}

private:
double m_d;
};

int main(int, char*[])
{
A a( 2.0 );
wcout << funcp( a.f ) << endl; // ERROR
// (I expect "6.0")
return 0;
}


The compiler (Microsoft cl.exe 12.00.8168) complains that it cannot
convert parameter 1 from 'double (double)' to 'double (__cdecl
*)(double)'.
It looks like pointers to function and pointers to members are not
interchangeable, and Stroustrup seems to confirm that. But are the
latter somehow adaptable to the former? The standard library gives a
similar facility (with mem_fun, fun_ptr and the like) but I doubt that
this is useful to me.

Thanks for your help.

Regards,
Giulio

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Thomas Richter
Guest





PostPosted: Tue Feb 24, 2004 1:43 pm    Post subject: Re: Pointers to function and pointers to members Reply with quote




Quote:
Hi there,

I am dealing with a C library, in particular with a function that
takes a pointer to function. To keep it simple let's say

void libf( double(*fun)(double) )
{
fun( 3.0 );
}

I would like to know if it's possible to call this function with the
pointer to a member function of a specific object (i.e. with some
state associated to it).

No, it's not. A pointer to a function and a pointer to a member
function are two very separate things. Remember, a pointer to a member
function has to carry the object around it is a member of. A regular
function pointer doesn't. (It is customary that pointers to member
functions are implemented as pairs of function pointer and class pointer).

However, what you *can* do is to take the address of a static(!) member
function and pass this as function pointer. You then need to give that
static member function an argument for the class it shall operate on,
of course. A typical solution would be to have a "wrapper function" that
calls the method of the class, e.g.:

class FooBar {
//
void DoSomeStrangeStuff();
//
static void CallbackWrapper(FooBar *that)
{
that->DoSomeStrangeStuff();
}
};

So long,
Thomas


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Steve Dewhurst
Guest





PostPosted: Tue Feb 24, 2004 7:11 pm    Post subject: Re: Pointers to function and pointers to members Reply with quote



Giulio Cespuglio <guilio (AT) despammed (DOT) com> wrote


Quote:
The compiler (Microsoft cl.exe 12.00.8168) complains that it cannot
convert parameter 1 from 'double (double)' to 'double (__cdecl
*)(double)'.
It looks like pointers to function and pointers to members are not
interchangeable, and Stroustrup seems to confirm that. But are the
latter somehow adaptable to the former? The standard library gives a
similar facility (with mem_fun, fun_ptr and the like) but I doubt that
this is useful to me.

No, you want to go the other way. It seems to me there must be a
standard solution for this, but I can't seem to recall one.

In any case, here's a quick non-thread-safe hack that perhaps you can
improve on:

template <class A, typename Ret, typename Arg>
struct Binder {
Binder( A &a, Ret (A::*f)(Arg) ) { a_ = &a; f_ = f; }
static double call( double d ) { return (a_->*f_)(d); }
static A *a_;
static Ret (A::*f_)(Arg);
};

template <class A, typename Ret, typename Arg>
A *Binder<A,Ret,Arg>::a_ = 0;

template <class A, typename Ret, typename Arg>
Ret (A::*(Binder<A,Ret,Arg>::f_))(Arg) = 0;

template <class A, typename Ret, typename Arg>
Ret (* bind( A &a, Ret (A::*f)(Arg) ) )(Arg) {
Binder<A,Ret,Arg> temp(a,f);
return Binder<A,Ret,Arg>::call;
};
//...
int main(int, char*[]){
using namespace std;

A a( 2.0 );
//cout << libf( a.f ) << endl; // ERROR (I expect "6.0")
cout << libf( bind(a,&A::f) ) << endl; // WORKS, but not safe

return 0;
}

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Gennaro Prota
Guest





PostPosted: Tue Feb 24, 2004 7:34 pm    Post subject: Re: Pointers to function and pointers to members Reply with quote

On 24 Feb 2004 08:43:18 -0500, Thomas Richter
<thor (AT) cleopatra (DOT) math.tu-berlin.de> wrote:

Quote:
(It is customary that pointers to member
functions are implemented as pairs of function pointer and class pointer).

Reality is quite more complex than that due to virtual functions and
multiple inheritance. Since the most general representation can be
quite large compilers generally allow some form of control through
command line switches. VC++, for instance, has /vmb, /vmg and the
#pragma pointers_to_members. Since the OP is using that compiler I
think a word of caution is due: by default VC++ will use a
representation that depends on how much it knows about the class when
it encounters the pointer declaration. This means it may use different
representations in different translation units because it has for
instance the full definition in one of them and just a declaration in
another one. And that, of course, can be disastrous if you use
references to pointers to members across translation units; e.g.:

-- C.hpp
// too lazy to put an include guard here ;)

class C {
public:
void mf (double) {}
};

-- file1.cpp
#include "C.hpp"

void f( void (C::*& pmf) (double), C* p );

int main() {

C c;
void (C::*p)(double) = &C::mf;

f(p, &c);

}

-- file2.cpp
class C;

void f( void (C::*& pmf) (double), C* p )
{
void (C::* copy)(double) = pmf; // oops... try
// including "C.hpp" instead
(p->*copy)(3.0);
}


If you have this kind of usage in your program it's up to you to
ensure a consistent representation through the appropriate switches
(or pragma).


Quote:
However, what you *can* do is to take the address of a static(!) member
function and pass this as function pointer.

It's not guaranteed by the standard, however: a static member function
is not extern "C".

--
Genny.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ben Hutchings
Guest





PostPosted: Wed Feb 25, 2004 11:46 pm    Post subject: Re: Pointers to function and pointers to members Reply with quote

Gennaro Prota wrote:
Quote:
On 24 Feb 2004 08:43:18 -0500, Thomas Richter
[email]thor (AT) cleopatra (DOT) math.tu-berlin.de[/email]> wrote:
snip
However, what you *can* do is to take the address of a static(!) member
function and pass this as function pointer.

It's not guaranteed by the standard, however: a static member function
is not extern "C".

However, friends can be, so here's a solution:

extern "C"
{
void c_func_with_callback(void (* callback)(void));
void my_class_callback(void);
}

class my_class
{
public:
my_class()
{
current_ = this;
c_func_with_callback(my_class_callback);
current_ = 0;
}

private:
friend void my_class_callback()
{
assert(current_);
current_->do_something();
}
void do_something();

// If multiple threads may instantiate the class concurrently,
// use TLS instead of static storage, or pass "this" through
// the C function as a pointer-to-void if possible.
static my_class * current_;
};

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Gennaro Prota
Guest





PostPosted: Wed Feb 25, 2004 11:59 pm    Post subject: Re: Pointers to function and pointers to members Reply with quote

On 24 Feb 2004 14:34:05 -0500, Gennaro Prota <gennaro_prota (AT) yahoo (DOT) com>
wrote:

Just a little note:

Quote:
And that, of course, can be disastrous if you use
references to pointers to members across translation units; e.g.:

Not that this is false, but pass by value isn't safe either Smile I had
in mind a different situation (and example), then mixed it up with
other things while writing the post. Of course you can reduce the
definition of f to

void f( void (C::* pmf)(double), C* p )
{
//oops...
(p->*pmf)(3.0);

}

and still get a crash.


--
Genny.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Gennaro Prota
Guest





PostPosted: Thu Feb 26, 2004 12:02 am    Post subject: Re: Pointers to function and pointers to members Reply with quote

On 24 Feb 2004 14:11:39 -0500, [email]scd (AT) semantics (DOT) org[/email] (Steve Dewhurst)
wrote:

Quote:
In any case, here's a quick non-thread-safe hack that perhaps you can
improve on:

Well, minor errors in the code apart (and the fact that in practice
several overloads of bind would be needed, including one for empty
argument lists), it really solves nothing. See my reply to Thomas or

http://std.dkuug.dk/jtc1/sc22/wg21/docs/cwg_closed.html#168


--
Genny.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.