Topic: type checking of member functions
Author: Jonathan de Boyne Pollard <J.deBoynePollard@tesco.net>
Date: 2000/05/25 Raw View
Barry Margolin <barmar@bbnplanet.com> wrote:
> [...]
> If f1() doesn't need to access an associated object, then you could
> make it static. Then it will be type-compatible with a
> similarly-prototyped non-member function.
But *not* necessarily linkage compatible.
This is a common mistake. It occurs regularly in comp.programming.threads,
where people want to pass non-static function members to pthread_create() (or
DosCreateThread(), or _beginthread(), or whatever) as the "callback" function
and they are told by others to pass static function members instead.
That piece of advice, like yours, is incorrect because there are several C++
implementations in common use where the linkage of member functions, even
_static_ member functions, is different to the linkage of non-member
functions. In particular, the calling conventions of member functions often
differ from the calling conventions of non-member functions, and a function
that expects a non-member function as a callback will cause unexpected
behaviour when it is passed the address of a member function by mistake.
In general, for portability (and correct operation on several
implementations), if a particular function expects to receive a non-member
function as a parameter for use as a callback, then a non-member function is
what one should pass. One should *not* pass a member function, even a static
one.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 2000/05/25 Raw View
Jonathan de Boyne Pollard wrote:
....
> That piece of advice, like yours, is incorrect because there are several C++
> implementations in common use where the linkage of member functions, even
> _static_ member functions, is different to the linkage of non-member
> functions. In particular, the calling conventions of member functions often
> differ from the calling conventions of non-member functions, and a function
> that expects a non-member function as a callback will cause unexpected
> behaviour when it is passed the address of a member function by mistake.
The key question is whether such implementations are conforming. Where
is the wording that allows that "unexpected behavior" when function
pointer happens to point at a static member function?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jose N Hinckel <hinckel@dem.inpe.br>
Date: 2000/04/04 Raw View
from : Jos N Hinckel
A recurring problem im my C++ applications
Given an algebraic function
float func(float);
and a root finding routine:
float root( float (*pf)(float), float guess1, float guess2, float tol);
Now have a class
class X {
float a;
float x1, x2, xt;
..
float f1(float);
/* problem here: Would like to use root finding routine "root" with
"f1", but can't
because "f1" is of type: float (X::*)(float) and root requires
requires float (*)(float). */
a = root(f1, x1, x2, xt) // illegal
...
};
Any good reason for this restriction?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Barry Margolin <barmar@bbnplanet.com>
Date: 2000/04/04 Raw View
In article <38E8E431.80643102@dem.inpe.br>,
Jose N Hinckel <hinckel@dem.inpe.br> wrote:
>
>from : Jos N Hinckel
>
>A recurring problem im my C++ applications
>
>Given an algebraic function
>
>float func(float);
>
>and a root finding routine:
>
>float root( float (*pf)(float), float guess1, float guess2, float tol);
>
>Now have a class
>
>class X {
>float a;
>float x1, x2, xt;
>..
>float f1(float);
>/* problem here: Would like to use root finding routine "root" with
>"f1", but can't
>because "f1" is of type: float (X::*)(float) and root requires
>requires float (*)(float). */
>
>a = root(f1, x1, x2, xt) // illegal
>
>...
>};
>
>Any good reason for this restriction?
Yes. Non-static member functions are typically invoked differently than
normal functions, because of the need to pass an implicit "this" parameter.
When the root() function calls pf, it will use the non-member calling
sequence.
If f1() doesn't need to access an associated object, then you could make it
static. Then it will be type-compatible with a similarly-prototyped
non-member function.
--
Barry Margolin, barmar@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jose N Hinckel <hinckel@dem.inpe.br>
Date: 2000/04/05 Raw View
Barry Margolin wrote:
> In article <38E8E431.80643102@dem.inpe.br>,
> Jose N Hinckel <hinckel@dem.inpe.br> wrote:
> >
> >from : Jos N Hinckel
> >
> >A recurring problem im my C++ applications
> >
> >Given an algebraic function
> >
> >float func(float);
> >
> >and a root finding routine:
> >
> >float root( float (*pf)(float), float guess1, float guess2, float tol);
> >
> >Now have a class
> >
> >class X {
> >float a;
> >float x1, x2, xt;
> >..
> >float f1(float);
> >/* problem here: Would like to use root finding routine "root" with
> >"f1", but can't
> >because "f1" is of type: float (X::*)(float) and root requires
> >requires float (*)(float). */
> >
> >a = root(f1, x1, x2, xt) // illegal
> >
> >...
> >};
> >
> >Any good reason for this restriction?
>
> Yes. Non-static member functions are typically invoked differently than
> normal functions, because of the need to pass an implicit "this" parameter.
> When the root() function calls pf, it will use the non-member calling
> sequence.
That is clear. Now one more point:
Is this restriction due to implementation problem (compiler) or does it serve some
other purposes of enforcing some premisse of the language? (Would it's relaxation
open doors
to any dark room?)
It is just that this construction would be very convenient.
>
> If f1() doesn't need to access an associated object, then you could make it
> static. Then it will be type-compatible with a similarly-prototyped
> non-member function.
Yes, f1() does need to access an associated object. A work around I have used is
declaring
pointer ouside the class and assigning it to this. (I call the root() function with
f1(), f2(), etc).
It works, but it is definitely a work around.
Thanks
>
>
> --
> Barry Margolin, barmar@bbnplanet.com
> GTE Internetworking, Powered by BBN, Burlington, MA
> *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
> Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "David J. Littleboy" <davidjl@gol.com>
Date: 2000/04/06 Raw View
Jose N Hinckel <hinckel@dem.inpe.br> wrote in message
> Yes, f1() does need to access an associated object. A work around I have
used is
> declaring
> pointer ouside the class and assigning it to this. (I call the root()
function with
> f1(), f2(), etc).
> It works, but it is definitely a work around.
Since your f1 requires two arguments (an object of class X and a float), it
doesn't match the requirements of your root-finding routine (which requires
a function of _one_ argument). In principle, you _have_ to do something to
convert between these requirements. (I see this less as a work around than
as a necessary part of program design.)
You could define an operator() for your class X and pass an object of type X
to your root finder as the function. If you define your root finder as a
template to use other function object types, you'll have what you want.
class X {
float val;
public:
X(float x) { val = x; }
float operator() (float z29) { return val + z29; };
};
float root(X &pf, float a, float b, float c);
int main ()
{
X myInstance(1.0);
cout << X(1.0)(2.0) << endl;
cout << root(X(1.0), 2.0, 3.0, 4.0) << endl;
return 0;
}
float root(X &pf, float a, float b, float c)
{
return pf(a) + pf(b) + pf(c);
}
--
David J. Littleboy <davidjl@gol.com>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Peter Hallowes" <phallowes@berty.com>
Date: 2000/04/06 Raw View
Jose N Hinckel <hinckel@dem.inpe.br> wrote in message
news:38E9F1D3.CFB18CA8@dem.inpe.br...
>
>
> Barry Margolin wrote:
>
> > In article <38E8E431.80643102@dem.inpe.br>,
> > Jose N Hinckel <hinckel@dem.inpe.br> wrote:
> > >
> > >from : Jos N Hinckel
> > >
> > >A recurring problem im my C++ applications
> > >
> > >Given an algebraic function
> > >
> > >float func(float);
> > >
> > >and a root finding routine:
> > >
> > >float root( float (*pf)(float), float guess1, float guess2, float tol);
> > >
> > >Now have a class
> > >
> > >class X {
> > >float a;
> > >float x1, x2, xt;
> > >..
> > >float f1(float);
> > >/* problem here: Would like to use root finding routine "root" with
> > >"f1", but can't
> > >because "f1" is of type: float (X::*)(float) and root requires
> > >requires float (*)(float). */
> > >
> > >a = root(f1, x1, x2, xt) // illegal
> > >
> > >...
> > >};
> > >
> > >Any good reason for this restriction?
> >
> > Yes. Non-static member functions are typically invoked differently than
> > normal functions, because of the need to pass an implicit "this"
parameter.
> > When the root() function calls pf, it will use the non-member calling
> > sequence.
>
> That is clear. Now one more point:
> Is this restriction due to implementation problem (compiler) or does it
serve some
> other purposes of enforcing some premisse of the language? (Would it's
relaxation
> open doors
> to any dark room?)
> It is just that this construction would be very convenient.
>
>
"The simplest way to implement a call to a member function is for a compiler
to
transform it into an ordinary function call in the generated code. A pointer
to the
object for which the member function is called - its this pointer - is
needed.
eg. A *pa; pa->f(2)
could be transformed into
f(pa, 2)
This implies that calling a C++ member function does not incur run-time
overheads
compared to a C function call.
> >
> > If f1() doesn't need to access an associated object, then you could make
it
> > static. Then it will be type-compatible with a similarly-prototyped
> > non-member function.
>
> Yes, f1() does need to access an associated object. A work around I have
used is
> declaring
> pointer ouside the class and assigning it to this. (I call the root()
function with
> f1(), f2(), etc).
> It works, but it is definitely a work around.
>
> Thanks
>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]