Topic: std::vector pointer


Author: Michiel.Salters@logicacmg.com (Michiel Salters)
Date: Fri, 4 Jun 2004 16:08:21 +0000 (UTC)
Raw View
jpotter@falcon.lhup.edu (John Potter) wrote in message news:<M_Itc.2728$Yd3.1882@newsread3.news.atl.earthlink.net>...
> On Thu, 27 May 2004 04:46:00 +0000 (UTC), jdennett@acm.org (James
> Dennett) wrote:
>
> Other citations removed because only this uncited one matters.
>
> > >>>  However, conversions between pointer to object and pointer to function
> > >>> are not allowed.  Hence, conversions between pointer to void (an
> > >>> incomplete object type) and function pointers are not allowed, even
> > >>> with an explicit cast.
>
> > I'm not sure if it's been done, but it would have made sense
> > for it to be implementation defined whether this would (a) work
> > or (b) be diagnosed at compile time, with no other options
> > allowed.  Both choices are sensible, and between them they seem
> > to cover everything that's needed.
>
> This does not make sense to me.  I do not think there is any precident
> for something which is implementation defined to be either well-formed
> and well-behaved or ill-formed.

Not yet, but there is definitely a feeling that such an extension is
warranted. The alternative is making this undefined; the current
"ill-formed" is considered even worse.

If this new category is implemented for C++0x, some other troublesome
cases may be put under it as well. This would be used to reduce the
number of cases of undefined behavior. Better to be loudly unportable
than silently unportable.

(Note for alt.comp.lang.learn.c-c++ : this isn't important yet)

> In the above quote, the cast is ill-formed.  That is also what is said
> in the C++ stantard by stating for each cast that any other attempt is
> ill-formed.  There is no anything behavior for something which is
> ill-formed.

Not true; an implementation is free to attach any behavior to it
provided that is has first issued a diagnotic. The standard doesn't
make a distinction between errors and warnings. After either one is
issued, the developer knows he'll have to look at the code.

Regards,
Michiel Salters

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: do-not-spam-benh@bwsint.com (Ben Hutchings)
Date: Wed, 2 Jun 2004 18:18:21 +0000 (UTC)
Raw View
John Potter wrote:
<snip>
> Is there any implementation where pointer to function is compatible with
> void* and there is no integral type which is also compatible?

There are implementations where there is no such *standard* integral
type.

> If not, there is no practical problem.  Extending the cast to allow
> the direct conversion is also available to any implementation where
> it will work.
>
> Having looked back through the thread to find the original question,
> here is a unix/windows solution for C/C++.
>
> #include <cstdio>
> #include <iostream>
> void f1 () { }
> void f2 () { }
> int main () {
>     printf("%p\n", (void*)(unsigned long) f1);
>     printf("%p\n", (void*)(unsigned long) f2);
>     std::cout << (void*)(unsigned long) f1 << "\n";
>     std::cout << (void*)(unsigned long) f2 << "\n";
>     }

This breaks on 64-bit Windows where unsigned long is normally 32-bit.
size_t should be a suitable substitute on all recent implementations
for Windows or Unix, and indeed in most environments with a flat
memory model.

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Robert W Hand <rwhand@NOSPAMoperamail.com>
Date: Thu, 27 May 2004 20:59:52 CST
Raw View
On Thu, 27 May 2004 04:46:00 +0000 (UTC), jdennett@acm.org (James
Dennett) wrote:

>Francis Glassborow wrote:
>> In message <rgUsc.7593$_o.5438@fed1read05>, James Dennett
>> <jdennett@acm.org> writes
>>
>>>>  However, conversions between pointer to object and pointer to function
>>>> are not allowed.  Hence, conversions between pointer to void (an
>>>> incomplete object type) and function pointers are not allowed, even
>>>> with an explicit cast.
>>>
>>>
>>> I think that it's been left as implementation-defined,
>>> to allow the many common implementations where a data
>>> pointer and a function pointer share a common representation.
>>> This is one of the places where the rules may be subtly
>>> different between C and C++, and I'm not sure of the fine
>>> points.
>>
>>
>> No, making it implementation defined would mean that it must always do
>> something sensible. However there is no reasonable way to handle this
>> if, for example, sizeof(void*) < sizeof(func*). However any
>> implementation can elect to make undefined behaviour defined. Indeed
>> this is case is a good example of why some things have undefined
>> behaviour, they cannot be done on all systems yet some systems can
>> provide a reasonable result.
>
>I'm not sure if it's been done, but it would have made sense
>for it to be implementation defined whether this would (a) work
>or (b) be diagnosed at compile time, with no other options
>allowed.  Both choices are sensible, and between them they seem
>to cover everything that's needed.

The quoted paragraph at the top was based on the C Standard for a
reference.  I believe that the C++ Standard is generally similar to
the C Standard with respect to converting a pointer to object to
pointer to function or vice versa.  The C++ Standard scatters this
material in the subclauses on conversions, static_cast operator, and
the reinterpret_cast operator.  I suspect that there is a historical
reason for this restriction.

Going back to the old days of 16 bit Windows and DOS, you may remember
that memory was divided into segments.  Pointers were divided into far
and near pointers.  Code and data were segregated into different
segments.  A near pointer would point into say the data segment.  No
matter what new value that near pointer would be given, it would still
point into the data segment, as I remember.  A far pointer would be
needed to switch into a different segment of memory.

I am revisiting this old memory model to show that during the
formative period of the Standards, a popular operating system memory
model did not allow conversions from every pointer to object to any
pointer to function.  So I suspect that the Standards committee felt
that it was better to leave this conversion undefined.  Perhaps
someone will have a better reason.

Best wishes,

Bob

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Wed, 2 Jun 2004 17:31:50 +0000 (UTC)
Raw View
On Thu, 27 May 2004 04:46:00 +0000 (UTC), jdennett@acm.org (James
Dennett) wrote:

Other citations removed because only this uncited one matters.

> >>>  However, conversions between pointer to object and pointer to function
> >>> are not allowed.  Hence, conversions between pointer to void (an
> >>> incomplete object type) and function pointers are not allowed, even
> >>> with an explicit cast.

> I'm not sure if it's been done, but it would have made sense
> for it to be implementation defined whether this would (a) work
> or (b) be diagnosed at compile time, with no other options
> allowed.  Both choices are sensible, and between them they seem
> to cover everything that's needed.

This does not make sense to me.  I do not think there is any precident
for something which is implementation defined to be either well-formed
and well-behaved or ill-formed.

In the above quote, the cast is ill-formed.  That is also what is said
in the C++ stantard by stating for each cast that any other attempt is
ill-formed.  There is no anything behavior for something which is
ill-formed.

Given Ptf is a pointer to some function type.

void f (Ptf ptf, void* ptv) {
   ptf = (Ptf)ptv;   // ill-formed diagnostic required
   ptv = (void*)ptf; // ill-formed diagnostic required
   ptf = (Ptf)(unsigned long)ptv;
   ptv = (void*)(unsigned long)ptf;
   }

The last two are well-formed with implementation defined mappings which
are not expected to surprise one who knows the addressing.  It is
interesting that the standard does say the cast to an integral type
large enough to hold it is valid.  Replacing long with char got an error
from one compiler, a warning from a second, and silence from a third.
At least one of them thinks the cast is implementation defined to be
ill-formed.

Is there any implementation where pointer to function is compatible with
void* and there is no integral type which is also compatible?  If not,
there is no practical problem.  Extending the cast to allow the direct
conversion is also available to any implementation where it will work.

Having looked back through the thread to find the original question,
here is a unix/windows solution for C/C++.

#include <cstdio>
#include <iostream>
void f1 () { }
void f2 () { }
int main () {
    printf("%p\n", (void*)(unsigned long) f1);
    printf("%p\n", (void*)(unsigned long) f2);
    std::cout << (void*)(unsigned long) f1 << "\n";
    std::cout << (void*)(unsigned long) f2 << "\n";
    }

John

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jdennett@acm.org (James Dennett)
Date: Thu, 27 May 2004 04:46:00 +0000 (UTC)
Raw View
Francis Glassborow wrote:
> In message <rgUsc.7593$_o.5438@fed1read05>, James Dennett
> <jdennett@acm.org> writes
>
>>>  However, conversions between pointer to object and pointer to function
>>> are not allowed.  Hence, conversions between pointer to void (an
>>> incomplete object type) and function pointers are not allowed, even
>>> with an explicit cast.
>>
>>
>> I think that it's been left as implementation-defined,
>> to allow the many common implementations where a data
>> pointer and a function pointer share a common representation.
>> This is one of the places where the rules may be subtly
>> different between C and C++, and I'm not sure of the fine
>> points.
>
>
> No, making it implementation defined would mean that it must always do
> something sensible. However there is no reasonable way to handle this
> if, for example, sizeof(void*) < sizeof(func*). However any
> implementation can elect to make undefined behaviour defined. Indeed
> this is case is a good example of why some things have undefined
> behaviour, they cannot be done on all systems yet some systems can
> provide a reasonable result.

I'm not sure if it's been done, but it would have made sense
for it to be implementation defined whether this would (a) work
or (b) be diagnosed at compile time, with no other options
allowed.  Both choices are sensible, and between them they seem
to cover everything that's needed.

Cross-posted to comp.std.c++, where we're likely to get more
in-depth answers and where this is more topical -- it's drifting
outside of the normal diet of alt.comp.lang.learn.c-c++.

-- James

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]