* function pointers in C++
@ 2004-03-15 9:28 elathan
2004-03-15 10:27 ` Jan-Benedict Glaw
` (2 more replies)
0 siblings, 3 replies; 11+ messages in thread
From: elathan @ 2004-03-15 9:28 UTC (permalink / raw)
To: linux-c-programming
Hello!
Suppose I have:
class Foo
{
public:
Foo();
~Foo();
int bar(int);
};
Now, why I can't do this:
Foo *f = new Foo();
taz(f->bar);
Where taz()'s protype is:
void taz(int (*f)(int));
In plain C, I can do:
int f(int) { ... }
taz(f);
without a problem. Is there a way to accomplish such a thing (i.e.
to pass the pointer of a C++ class's member function to another
function that expects a pointer to function as an argument)?
Regards,
--
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: function pointers in C++
2004-03-15 9:28 elathan
@ 2004-03-15 10:27 ` Jan-Benedict Glaw
2004-03-15 10:39 ` elathan
2004-03-15 14:38 ` Darío Mariani
2004-03-15 19:10 ` Ashutosh Ranjan
2 siblings, 1 reply; 11+ messages in thread
From: Jan-Benedict Glaw @ 2004-03-15 10:27 UTC (permalink / raw)
To: linux-c-programming
[-- Attachment #1: Type: text/plain, Size: 796 bytes --]
On Mon, 2004-03-15 11:28:19 +0200, elathan@phys.uoa.gr <elathan@phys.uoa.gr>
wrote in message <1079342899.405577335bb24@webmail.uoa.gr>:
> Hello!
>
> Suppose I have:
>
> class Foo
> {
> public:
> Foo();
> ~Foo();
> int bar(int);
> };
>
> Now, why I can't do this:
>
> Foo *f = new Foo();
> taz(f->bar);
>
> Where taz()'s protype is:
>
> void taz(int (*f)(int));
You're looking for "static"ally declared member functions.
MfG, JBG
--
Jan-Benedict Glaw jbglaw@lug-owl.de . +49-172-7608481
"Eine Freie Meinung in einem Freien Kopf | Gegen Zensur | Gegen Krieg
fuer einen Freien Staat voll Freier Bürger" | im Internet! | im Irak!
ret = do_actions((curr | FREE_SPEECH) & ~(NEW_COPYRIGHT_LAW | DRM | TCPA));
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: function pointers in C++
2004-03-15 10:27 ` Jan-Benedict Glaw
@ 2004-03-15 10:39 ` elathan
0 siblings, 0 replies; 11+ messages in thread
From: elathan @ 2004-03-15 10:39 UTC (permalink / raw)
To: Jan-Benedict Glaw; +Cc: linux-c-programming
Jan-Benedict Glaw <jbglaw@lug-owl.de>:
> On Mon, 2004-03-15 11:28:19 +0200, elathan@phys.uoa.gr <elathan@phys.uoa.gr>
> > void taz(int (*f)(int));
>
> You're looking for "static"ally declared member functions.
And in that case I can't use 'this' inside the function. Brilliant... :-(
Thanx for the reply.
Regards,
--
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: function pointers in C++
2004-03-15 14:21 function pointers in C++ Sandro Dangui
@ 2004-03-15 11:28 ` Elias Athanasopoulos
2004-03-16 7:50 ` Glynn Clements
0 siblings, 1 reply; 11+ messages in thread
From: Elias Athanasopoulos @ 2004-03-15 11:28 UTC (permalink / raw)
To: Sandro Dangui; +Cc: linux-c-programming, Dar?o Mariani
On Mon, Mar 15, 2004 at 11:21:18AM -0300, Sandro Dangui wrote:
>
> I think this sample code will help you... Verify if it looks brilliant
> enough. :-))
Thanks for the detailed reply.
Actually, what I want to do is to pass a pointer to a member function in
a function that expects a pointer to function; I don't want to call the
member function, but just pass its address.
Following Stroustrup (pages 156..158), I did something like this:
Foo *f = new Foo(id);
double (Foo::*pfunc)(double *, double *) = &Foo::func;
Bar *res = new Bar((double (*)(double *, double *))(func->*pfunc));
And:
class Foo {
public:
Foo(int id);
~Foo();
double func(double *, double *);
};
Also Bar's constructor (I can't change it --third party implementation) is:
Bar(double (*)(double *, double *));
Amazingly I get the error:
test.cxx:107: error: converting from `double (Foo::*)(double*, double*)' to
`double (*)(double*, double*)'
which is *at least* annoying. It is another BIG suprise from C++. I mean,
there is, most probably, a good reason why this is not supported, but it is
a *broken design*.
Foo::func()'s prototype is (double) (double *, double *), which in my human
brain is compiled as: 'give me two pointers to double and I will give you one
double'. Why I can't pass it to a function which *expects* what my poor human brain
understands?
I didn't ask to convert for me a string to float...
Regards,
--
University of Athens I bet the human brain
Physics Department is a kludge --Marvin Minsky
^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: function pointers in C++
@ 2004-03-15 14:21 Sandro Dangui
2004-03-15 11:28 ` Elias Athanasopoulos
0 siblings, 1 reply; 11+ messages in thread
From: Sandro Dangui @ 2004-03-15 14:21 UTC (permalink / raw)
To: elathan; +Cc: linux-c-programming
I think this sample code will help you... Verify if it looks brilliant
enough. :-))
----------------------------------------------------------------------------
--------------------
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
// definitions for portability
#ifdef _WIN32
#define STDCALL __cdecl
#else
#define STDCALL
#endif
class Foo
{
public:
Foo(int id)
{
Id = id;
}
int STDCALL bar(int value)
{
printf("Method Foo::bar with param value=%i, Foo Id=%i\n",
value, Id);
return (value * 2 + Id);
}
protected:
int Id;
};
class CallFooMethod
{
public:
CallFooMethod(void* pInstance, ...)
{
va_list argList;
va_start(argList, pInstance);
pObject = pInstance;
pMethod = va_arg(argList, void *);
va_end(argList);
}
int CallIt(int value)
{
typedef int (*F)(void *, int);
F f = (F) pMethod;
/* The trick here is that the compiler pass the "this" value
as a hidden parameter... Then,
let's do the same thing explicitly */
return f(pObject, value);
}
protected:
void* pObject;
void* pMethod;
};
int main(int /*argc*/, char** /*argv*/)
{
Foo foo1(1);
Foo foo2(2);
CallFooMethod callFooMethod1(&foo1, &Foo::bar);
CallFooMethod callFooMethod2(&foo2, &Foo::bar);
int retValue1 = callFooMethod1.CallIt(50);
int retValue2 = callFooMethod2.CallIt(100);
printf("retValue1=%i, retValue2=%i\n", retValue1, retValue2);
return 0;
}
----------------------------------------------------------------------------
--------------------
-----Original Message-----
From: linux-c-programming-owner@vger.kernel.org
[mailto:linux-c-programming-owner@vger.kernel.org] On Behalf Of
elathan@phys.uoa.gr
Sent: Monday, March 15, 2004 7:40 AM
To: Jan-Benedict Glaw
Cc: linux-c-programming@vger.kernel.org
Subject: Re: function pointers in C++
Jan-Benedict Glaw <jbglaw@lug-owl.de>:
> On Mon, 2004-03-15 11:28:19 +0200, elathan@phys.uoa.gr
> <elathan@phys.uoa.gr>
> > void taz(int (*f)(int));
>
> You're looking for "static"ally declared member functions.
And in that case I can't use 'this' inside the function. Brilliant... :-(
Thanx for the reply.
Regards,
--
-
To unsubscribe from this list: send the line "unsubscribe
linux-c-programming" in the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: function pointers in C++
2004-03-15 9:28 elathan
2004-03-15 10:27 ` Jan-Benedict Glaw
@ 2004-03-15 14:38 ` Darío Mariani
2004-03-15 14:56 ` Darío Mariani
2004-03-15 19:10 ` Ashutosh Ranjan
2 siblings, 1 reply; 11+ messages in thread
From: Darío Mariani @ 2004-03-15 14:38 UTC (permalink / raw)
To: linux-c-programming
Probably what you need is the "pointer to member". It's described in
chapter 15, section 5 in "The C++ Programming Language", from Stroustrup.
elathan@phys.uoa.gr wrote:
> Hello!
>
> Suppose I have:
>
> class Foo
> {
> public:
> Foo();
> ~Foo();
> int bar(int);
> };
>
> Now, why I can't do this:
>
> Foo *f = new Foo();
> taz(f->bar);
>
> Where taz()'s protype is:
>
> void taz(int (*f)(int));
>
> In plain C, I can do:
>
> int f(int) { ... }
> taz(f);
>
> without a problem. Is there a way to accomplish such a thing (i.e.
> to pass the pointer of a C++ class's member function to another
> function that expects a pointer to function as an argument)?
>
> Regards,
> --
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: function pointers in C++
2004-03-15 14:38 ` Darío Mariani
@ 2004-03-15 14:56 ` Darío Mariani
0 siblings, 0 replies; 11+ messages in thread
From: Darío Mariani @ 2004-03-15 14:56 UTC (permalink / raw)
Cc: linux-c-programming
Some time ago I made a small library to tackle this problem, it's in
http://sourceforge.net/projects/cppcback/
Also there is an implementation of a similar mechanism in the libraries
found in http://www.boost.org.
Darío Mariani wrote:
> Probably what you need is the "pointer to member". It's described in
> chapter 15, section 5 in "The C++ Programming Language", from Stroustrup.
>
> elathan@phys.uoa.gr wrote:
>
>> Hello!
>> Suppose I have:
>> class Foo { public: Foo(); ~Foo(); int bar(int); };
>> Now, why I can't do this:
>> Foo *f = new Foo(); taz(f->bar);
>> Where taz()'s protype is:
>> void taz(int (*f)(int));
>> In plain C, I can do:
>> int f(int) { ... } taz(f);
>> without a problem. Is there a way to accomplish such a thing (i.e. to
>> pass the pointer of a C++ class's member function to another function
>> that expects a pointer to function as an argument)?
>> Regards, --
>> -
>> To unsubscribe from this list: send the line "unsubscribe
>> linux-c-programming" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
>
>
> -
> To unsubscribe from this list: send the line "unsubscribe
> linux-c-programming" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
-
To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: function pointers in C++
2004-03-15 9:28 elathan
2004-03-15 10:27 ` Jan-Benedict Glaw
2004-03-15 14:38 ` Darío Mariani
@ 2004-03-15 19:10 ` Ashutosh Ranjan
2 siblings, 0 replies; 11+ messages in thread
From: Ashutosh Ranjan @ 2004-03-15 19:10 UTC (permalink / raw)
To: elathan; +Cc: linux-c-programming@vger.kernel.org
hi.
well check out mem_fun() which is standard library function...this takes
the pointer to a member function as its argument and produces something
that can be called for a pointer to the member's class.
Ex for your code...
taz(mem_function(&Foo::bar) should work...it should take the Foo*
argument and return what Foo::bar() returns !!
regards,
Ashu
On Mon, 2004-03-15 at 14:58, elathan@phys.uoa.gr wrote:
> Hello!
>
> Suppose I have:
>
> class Foo
> {
> public:
> Foo();
> ~Foo();
> int bar(int);
> };
>
> Now, why I can't do this:
>
> Foo *f = new Foo();
> taz(f->bar);
>
> Where taz()'s protype is:
>
> void taz(int (*f)(int));
>
> In plain C, I can do:
>
> int f(int) { ... }
> taz(f);
>
> without a problem. Is there a way to accomplish such a thing (i.e.
> to pass the pointer of a C++ class's member function to another
> function that expects a pointer to function as an argument)?
>
> Regards,
> --
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: function pointers in C++
@ 2004-03-15 21:59 Sandro Dangui
0 siblings, 0 replies; 11+ messages in thread
From: Sandro Dangui @ 2004-03-15 21:59 UTC (permalink / raw)
To: Elias Athanasopoulos; +Cc: linux-c-programming
You got this error: converting from `double (Foo::*)(double*, double*)' to
`double (*)(double*, double*)' because the compiler doesn't know which
instance of class Foo it should use in the call... As I said before the
compiler pass the "this" value (that represents an instance of a class) as a
hidden parameter.
So, the only possible solution that I can see is the use of static method.
Do you need multiple instances of the class that implements the desired
method? Or can you use a singleton? Using a singleton your static method
will have access to other methods and attributes through the static method
getInstance().
Sandro.
-----Original Message-----
From: Elias Athanasopoulos [mailto:elathan@phys.uoa.gr]
Sent: Monday, March 15, 2004 8:29 AM
To: Dangui, Sandro [CMPS:RY11:EXCH]
Cc: linux-c-programming@vger.kernel.org; Dar?o Mariani
Subject: Re: function pointers in C++
On Mon, Mar 15, 2004 at 11:21:18AM -0300, Sandro Dangui wrote:
>
> I think this sample code will help you... Verify if it looks brilliant
> enough. :-))
Thanks for the detailed reply.
Actually, what I want to do is to pass a pointer to a member function in a
function that expects a pointer to function; I don't want to call the member
function, but just pass its address.
Following Stroustrup (pages 156..158), I did something like this:
Foo *f = new Foo(id);
double (Foo::*pfunc)(double *, double *) = &Foo::func;
Bar *res = new Bar((double (*)(double *, double *))(func->*pfunc));
And:
class Foo {
public:
Foo(int id);
~Foo();
double func(double *, double *);
};
Also Bar's constructor (I can't change it --third party implementation) is:
Bar(double (*)(double *, double *));
Amazingly I get the error:
test.cxx:107: error: converting from `double (Foo::*)(double*, double*)' to
`double (*)(double*, double*)'
which is *at least* annoying. It is another BIG suprise from C++. I mean,
there is, most probably, a good reason why this is not supported, but it is
a *broken design*.
Foo::func()'s prototype is (double) (double *, double *), which in my human
brain is compiled as: 'give me two pointers to double and I will give you
one double'. Why I can't pass it to a function which *expects* what my poor
human brain understands?
I didn't ask to convert for me a string to float...
Regards,
--
University of Athens I bet the human brain
Physics Department is a kludge --Marvin Minsky
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: function pointers in C++
2004-03-15 11:28 ` Elias Athanasopoulos
@ 2004-03-16 7:50 ` Glynn Clements
2004-03-18 11:17 ` Elias Athanasopoulos
0 siblings, 1 reply; 11+ messages in thread
From: Glynn Clements @ 2004-03-16 7:50 UTC (permalink / raw)
To: Elias Athanasopoulos; +Cc: Sandro Dangui, linux-c-programming, Dar?o Mariani
Elias Athanasopoulos wrote:
> > I think this sample code will help you... Verify if it looks brilliant
> > enough. :-))
>
> Thanks for the detailed reply.
>
> Actually, what I want to do is to pass a pointer to a member function in
> a function that expects a pointer to function;
You can't. Member functions have an implicit "this" argument.
E.g. in your original example:
class Foo
{
public:
Foo();
~Foo();
int bar(int);
};
Foo::bar actually looks like this:
int bar(Foo *this, int);
so you can't pass it to something which wants "int (*func)(int)".
> I don't want to call the
> member function, but just pass its address.
>
> Following Stroustrup (pages 156..158), I did something like this:
>
> Foo *f = new Foo(id);
> double (Foo::*pfunc)(double *, double *) = &Foo::func;
> Bar *res = new Bar((double (*)(double *, double *))(func->*pfunc));
>
> And:
>
> class Foo {
> public:
> Foo(int id);
> ~Foo();
> double func(double *, double *);
> };
>
> Also Bar's constructor (I can't change it --third party implementation) is:
>
> Bar(double (*)(double *, double *));
>
> Amazingly I get the error:
>
> test.cxx:107: error: converting from `double (Foo::*)(double*, double*)' to
> `double (*)(double*, double*)'
No surprise there. Pointers to functions and pointers to members
aren't the same thing.
> which is *at least* annoying. It is another BIG suprise from C++. I mean,
> there is, most probably, a good reason why this is not supported, but it is
> a *broken design*.
>
> Foo::func()'s prototype is (double) (double *, double *),
No it isn't. If you ignore the fact that it's a member of class Foo,
it looks like that. But you *can't* ignore the fact that it's a member
of class Foo.
From a C perspective, Foo::func()s prototype looks more like:
double func(struct Foo *, double *, double *);
which isn't compatible with Bar's constructor.
If Bar's constructor takes a function pointer, chances are that
something within Bar is going to call that function at some point. And
it will call it with two pointers to doubles; it won't be passing
anything else, i.e. the "this" parameter which object methods require.
If you don't need a "this" pointer (even implictly; bear in mind that
a reference to a member variable "foo" is just shorthand for
"this->foo"), you can use a static method.
OTOH, if you do need a "this" pointer, then tough luck. Bar's
definition doesn't allow for that. A more useful definition of Bar
would use:
Bar(double (*)(void *, double *, double *), void *);
If Bar's implementors had done that, you would be able to write:
class Foo {
...
static double wrapper(void *, double *, double *);
};
double Foo::wrapper(void *p, double *a, double *b)
{
return ((Foo *)p)->func(a, b);
}
...
Foo *foo = new Foo();
Bar *bar = new Bar(&Foo::wrapper, (void *) foo);
However, they didn't, so you can't.
And there isn't any clean solution. Bar's constructor requires a
pointer to a function; a function which will be passed two pointers to
doubles, and *nothing else*. No "this" pointer. So the function's
return value can't depend on anything other than the two pointers
which it is passed, plus any global variables which it may return.
The closest you can get is to use a static variable or member, e.g.:
class Foo {
public:
static Foo *the_foo;
static double wrapper(double *a, double *b);
}
double Foo::wrapper(double *a, double *b)
{
return the_foo->func(a, b);
}
Foo *foo = new Foo();
Foo::the_foo = foo;
Bar *bar = new Bar(&Foo::wrapper);
If you want a fixed number of Foo's, you need one wrapper and one
static variable for each. If you want an arbitrary number of Foo's,
you're out of luck.
--
Glynn Clements <glynn.clements@virgin.net>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: function pointers in C++
2004-03-16 7:50 ` Glynn Clements
@ 2004-03-18 11:17 ` Elias Athanasopoulos
0 siblings, 0 replies; 11+ messages in thread
From: Elias Athanasopoulos @ 2004-03-18 11:17 UTC (permalink / raw)
To: Glynn Clements; +Cc: Sandro Dangui, linux-c-programming, Dar?o Mariani
On Tue, Mar 16, 2004 at 07:50:11AM +0000, Glynn Clements wrote:
> If you want a fixed number of Foo's, you need one wrapper and one
> static variable for each. If you want an arbitrary number of Foo's,
> you're out of luck.
Thanx Glynn for the detailed answer. It seems that I am out of luck
here, but your answer was very insightful.
Regards,
--
University of Athens I bet the human brain
Physics Department is a kludge --Marvin Minsky
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2004-03-18 11:17 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-03-15 14:21 function pointers in C++ Sandro Dangui
2004-03-15 11:28 ` Elias Athanasopoulos
2004-03-16 7:50 ` Glynn Clements
2004-03-18 11:17 ` Elias Athanasopoulos
-- strict thread matches above, loose matches on Subject: below --
2004-03-15 21:59 Sandro Dangui
2004-03-15 9:28 elathan
2004-03-15 10:27 ` Jan-Benedict Glaw
2004-03-15 10:39 ` elathan
2004-03-15 14:38 ` Darío Mariani
2004-03-15 14:56 ` Darío Mariani
2004-03-15 19:10 ` Ashutosh Ranjan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).