From 6819582241359749468
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f78e5,1e1d3ed27fda1584
X-Google-Attributes: gidf78e5,public
X-Google-ArrivalTime: 1994-04-18 11:23:21 PST
Newsgroups: comp.std.c++
Path: gmd.de!nntp.gmd.de!xlink.net!slsv6bt!slsv6bt!kanze
From: kanze@us-es.sel.de (James Kanze)
Subject: Re: casting class function addresses
In-Reply-To: jpcauvin@bongo.cc.utexas.edu's message of 9 Apr 1994 03:23:21 GMT
Message-ID: <KANZE.94Apr18192321@slsvhdt.us-es.sel.de>
Followup-To: comp.std.c++
Sender: news@lts.sel.alcatel.de
Organization: SEL
References: <jpcauvin-040494213746@slip-1-49.ots.utexas.edu>
	<jpcauvin-020494115637@slip-15-2.ots.utexas.edu>
	<pjl.765206128@graceland.att.com> <41768@mindlink.bc.ca>
	<BWH.94Apr2122342@beach.cis.ufl.edu> <9404041757.AA28726@ses.com>
	<9404081933.AA22782@ses.com>
	<jpcauvin-080494214617@slip-6-3.ots.utexas.edu>
Date: 18 Apr 1994 18:23:21 GMT
Lines: 88

In article <jpcauvin-080494214617@slip-6-3.ots.utexas.edu>
jpcauvin@bongo.cc.utexas.edu (Roger L. Cauvin) writes:

|> In article <9404081933.AA22782@ses.com>, jamshid@ses.com (Jamshid Afshar)
|> wrote:

|> ...

|> > JA>[...] Some current C++ compilers can optionally, at the
|> > JA>expense of letting ptm casts work, optimize the size of ptms.  It's
|> > JA>still very uncertain whether ANSI/ISO will allow this optimization [...]

|> ...

|> If *no* pointer to member function casts are guaranteed to work on these
|> compilers, then they are irrelevant to this discussion.  We have already
|> established that the ARM explicitly states that *some* pointer to member
|> function casting is allowed.

But not guaranteed to work:-).

What is, I think, fairly established, is that you can cast a pointer
to member to a pointer to member of a different class within the
hierarchy, then cast it back to the original type, and it will work.
I fail to find text in the ARM guaranteeing even this, much less
anything more, although the limitations concerning unambiguous
derivation (in section 5.4) are highly suggestive that more was meant.

|> I recognize the possibility that peculiarities in a compiler's
|> implementation of member function pointers could effect the reliability of
|> casting and dereferencing member function pointers.  The question is
|> whether such compiler peculiarities are ruled out, directly or indirectly,
|> by the ARM or ANSI/ISO.

For the moment, they are not clearly ruled out, so we have to consider
the probability that some implementor will have used them.

|> > Besides, my paragraph you quote above was in reference to your code:

|> > 	typedef void (A::*AFP)();
|> > 	typedef void (B::*BFP)();  // class B unrelated to A
|> > 	void g( AFP a ) {
|> > 	   BFP bfp = *(BFP*)&a;   // definitely undefined run-time behavior
|> > 	}

|> > Alignment requirements aside, nowhere does the ARM imply that this
|> > might work.  You can't treat a block of memory containing an object
|> > like it's a block of memory containing a different type of object.

|> You keep saying this (and giving exceptions), but you still haven't
|> provided compelling evidence that such a technique will not work in the
|> case of member function pointers.

Is the fact that it won't work with any of the compilers I currently
use compelling evidence?  It will work some of the time.  It will in
fact always work if there is no multiple inheritance in either of the
classes involved.  It will also work if neither of the pointers points
to an inherited member.  (The above holds for Sun CC, a cfront
variant.  The other compilers are somewhat different; at least one
simply forbids all casts of pointers to members.)

|> > I think there's one exception to this besides chars: the address of an
|> > aggregate is guaranteed to be the address of the first member:

|> > 	struct S { int i; } s;
|> > 	int* p = (int*)(void*)&s;  // okay: p points to s.i
|> > 	int a[10];
|> > 	int* q = (int*)(void*)&a;  // okay: q points to a[0]

|> > Note that the layout of non-aggregate classes is undefined:

|> > 	struct D : public S {};
|> > 	D d;
|> > 	int* p = (int*)(void*)&d;  // bad: (void*)&d is not necessarily equal
|> > 	                           // to (S*)&d

|> By the way, there's no need to cast the addresses to (void *) before
|> casting them to (int *).

But it is good style.  In the absense of the new cast syntax, a cast
to void* is about the best way I know of of ensuring that a
reinterpret_cast is involved, and of letting the reader know that this
is intentional.
--
James Kanze                       email: kanze@lts.sel.alcatel.de
GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                   -- Beratung in industrieller Datenverarbeitung


