 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Giulio Cespuglio Guest
|
Posted: Tue Feb 24, 2004 3:30 am Post subject: Pointers to function and pointers to members |
|
|
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
|
Posted: Tue Feb 24, 2004 1:43 pm Post subject: Re: Pointers to function and pointers to members |
|
|
| 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
|
Posted: Tue Feb 24, 2004 7:11 pm Post subject: Re: Pointers to function and pointers to members |
|
|
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
|
Posted: Tue Feb 24, 2004 7:34 pm Post subject: Re: Pointers to function and pointers to members |
|
|
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
|
Posted: Wed Feb 25, 2004 11:46 pm Post subject: Re: Pointers to function and pointers to members |
|
|
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
|
Posted: Wed Feb 25, 2004 11:59 pm Post subject: Re: Pointers to function and pointers to members |
|
|
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 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
|
Posted: Thu Feb 26, 2004 12:02 am Post subject: Re: Pointers to function and pointers to members |
|
|
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 |
|
 |
|
|
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
|
|