Topic: suitable_cast


Author: jpotter@falcon.lhup.edu (John E. Potter)
Date: 1997/03/20
Raw View
James Kanze (james-albert.kanze@vx.cit.alcatel.fr) wrote:
: schwab@issan.informatik.uni-dortmund.de (Andreas Schwab) writes:

: |>  James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
: |>
: |>  |> Basically, however, there are two points:
: |>
: |>  |> 1. A void* must be able to hold any pointer type without loss
: |>  |> of value.
: |>
: |>  I think that should be *data* pointer type.  A cast between function and
: |>  data pointer types is undefined.

: Correct.  Although I don't think anyone has explicitly said so, I think
: that the entire thread is only concerned with casts between pointers to
: data.

Yes, agreed, we are talking about pointers to object which excludes pointer
to function.  However, this does bring up an interesting point.  I have
the following code which is correct and works fine, but it seems that it
is ill-formed.

void f (void);
void* p = *reinterpret_cast<void**>(f);

I am not interested in portability here since it is obviously platform
dependant.  So, is the following well-formed?

void* p = *reinterpret_cast<void**>(reinterpret_cast<unsigned long>(f));

There are no restrictions on cast from pointer (object or function) to
and from integral type.  The mapping is implementation defined and of
course I can live with that.  But I can not live with a syntax error
in a future conforming compiler.

Thoughts?

John
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/13
Raw View
jpotter@falcon.lhup.edu (John E. Potter) writes:

|>  James Kanze (james-albert.kanze@vx.cit.alcatel.fr) wrote:
|>  > Valentin Bonnard <bonnardv@pratique.fr> writes:
|>  > |>  jpotter@falcon.lhup.edu (John E. Potter) wrote:
|>  > |>  > Various parts of the draft authorize the following, I think.
|>
|>   [ examples of doable things which have no simple cast ]
|>
|>  > |>  > My problem is finding suitable_cast.  It is easy to eliminate
|>  > |>  > const_cast, dynamic_cast and static_cast since these things are
|>  > |>  > not on the lists of doable things.  I can't use reinterpret_cast
|>  > |>  > because it is not portable.
|>
|>  > |>  > What do I use for sutiable_cast?
|>
|>  > |>  None, and it was the point of one of my posting in this newsgroup;
|>
|>  > I think that in this case, reinterpret_cast IS portable. At least, the
|>  > old style cast was portable in C, and an old style cast here has the
|>  > semantics of a reinterpret_cast, so it "should" be portable if C
|>  > compatibility is to be maintain.
|>
|>  Steve Clamage has pointed out many times that reinterpret_cast is "never"
|>  portable.  I agree that it "should" be portable; however, IMHO there
|>  should be a means in a standard to do things which are required by a
|>  standard to be doable.

This may be just hyperbole on Steve's part, but I suspect that he is
thinking in a larger sense.  You can portably reinterpret_cast a T* to
unsigned char*, and access the physical bytes, but what is in the bytes
is not defined, so you cannot do anything with them, portably.  (Note
that even memcpy, which probably does something like this internally, is
not guaranteed to work on all C++ types.)

|>  > Basically, however, there are two points:
|>
|>  > 1. A void* must be able to hold any pointer type without loss of value.
|>  > For historical reasons, this guarantee is extended to pointers to
|>  > character types.  So the "reinterpret_cast" cannot be value-losing in
|>  > this case.
|>
|>  Actually (3.9.2/4), void* is required to be like char*; and unlike void*,
|>  char* is dereferencable.  So reinterpret_cast cannot be value-losing;
|>  however, there is no requirement that the cast be dereferencable.  It
|>  must be possible to return the value if recast to the original type,
|>  but nothing is said about what can be done with the other type.  It is
|>  possible to tag the pointer to indicate that it is value preserving but
|>  not usable, I guess.

I'm not too sure here; I'd have to find the interpretation ruling of the
C standard.  Basically, however, the impact was that you can always
access the raw memory underneith the object as raw memory; the only type
guaranteed to work on raw memory, however, is unsigned char.

Of course, anything you might do with raw memory is inherantly
unportable; I guess, however, that outputting it as a dump to a file
would be legal.  (The actual data output is undefined, of course, but I
think that you can output it.)

|>  > 2. According to the interpretation ruling in C, "unsigned char" is a
|>  > special type, which is guaranteed to access raw memory, and every bit of
|>  > it. Note that this guarantee is ONLY extended to "unsigned char"; a
|>  > "signed char" is allowed, e.g. under 1's complement to convert negative
|>  > 0's (0xff) to positive ones on loading or storing.  And a plain char is
|>  > allowed to be signed.
|>
|>  The C standard is a normative reference (1.2); however, on reading it
|>  again, I think that it only says that any reference to it within the
|>  C++ standard is normative, not that it is included in its entirety.  The
|>  differences (C2) are given in an informative way.  The C standard is
|>  referenced in many places, in particular, with respect to the memory
|>  model.

That might be what we are looking for.  The use of "unsigned char" for
raw memory is part of the C memory model.

|>  In C++, an object may be accessed (3.10/15) via an lvalue of type unsigned
|>  char or char.

In C, a recent ruling limited this to just "unsigned char".  I believe
that it was actually unclear in the C standard.

In practice, if you allow char, but not signed char, either it also
works for signed char, or char is unsigned.

|>  However, I find no way to obtain an unsigned char* or a
|>  char* which points to an object in a portable way.  Raw memory may be
|>  accessed via memcpy (3.9/2) as an example; however, I think that
|>  would apply as well to unsigned char*.  Can I write myMemcpy:
|>
|>    void myMemcpy (void* dest, void* source, int bytes) {
|>     unsigned char* d(static_cast<unsigned char*>(dest));
|>     unsigned char* s(static_cast<unsigned char*>(source));
|>     for (; bytes > 0; -- bytes)
|>      *d++ = *s++;
|>        }
|>
|>  The standard conversion to void* in calling myMemcpy must point to the
|>  same object; so, I would assume that the static_cast from void* must
|>  also be value preserving.

|>  This leads to the conclusion that the
|>  suitable_cast that I am looking for is spelled
|>
|>    static_cast<desired*>(static_cast<void*>(somePtr));
|>
|>  as long as I stick to desired == typeof(somePtr), desired is
|>  char or unsigned char, or desired/typeof(somePtr) are POD struct and
|>  first member in either order(9.2/17).  Disgusting things to code though.
                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Given the implications of what is being done, that is probably a feature
(that they are disgusting things to code).  While sometimes necessary, I
see no reason to encourage such practices.

    [...]
|>  I have the feeling that in the beginning, static_cast may have been
|>  intended to be totally safe.  As it stands now, it includes the things
|>  which can be reasonably safe like casting down a hierarchy when one
|>  "knows" that it is possible and casting from void* to what one "knows"
|>  is reasonable.  I think that it would be reasonable to include the
|>  suitable_cast items in static_cast.  Anything* to char* or unsigned char*,
|>  POD struct* to/from first member*.  And for references.  Then
|>  reinterpret_cast could be the implementation defined, non-portable
|>  cast that we all know it is.  And the draft required doable things
|>  would be static_cast, dynamic_cast, const_cast or old style.

I don't think that it was ever the intent that static_cast be totally
safe; there is dynamic_cast for that.  The intent may have been that
static_cast cover casts that are sometimes reasonable (and sometimes
not) and generally portable.

If this is the case, I basically agree with your comments.

An alternative interpretation of the intent is that the static_cast was
meant to be opposed to reinterpret_cast: static_cast is, in some sense,
a conversion, and reinterpret_cast is type punning.  So that if pb
actually does point to a B in a D, static_cast< D* >( pb ) will point to
the complete D, whereas reinterpret_cast< D* >( pb ) will point to the
B, but says to pretend it is a D instead.

Under this interpretation, all of the casts to/from void*, etc. should
be reinterpret_cast's.

--
James Kanze      home:     kanze@gabi-soft.fr        +33 (0)1 39 55 85 62
                 office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
     -- Conseils en informatique industrielle --
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/13
Raw View
schwab@issan.informatik.uni-dortmund.de (Andreas Schwab) writes:

|>  James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
|>
|>  |> Basically, however, there are two points:
|>
|>  |> 1. A void* must be able to hold any pointer type without loss of value.
|>
|>  I think that should be *data* pointer type.  A cast between function and
|>  data pointer types is undefined.

Correct.  Although I don't think anyone has explicitly said so, I think
that the entire thread is only concerned with casts between pointers to
data.

--
James Kanze      home:     kanze@gabi-soft.fr        +33 (0)1 39 55 85 62
                 office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
     -- Conseils en informatique industrielle --
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/11
Raw View
Valentin Bonnard <bonnardv@pratique.fr> writes:

|>  jpotter@falcon.lhup.edu (John E. Potter) wrote:
|>  > Various parts of the draft authorize the following, I think.
|>  >
|>  > #include <iostream.h>
|>  > struct Student { int id; float gpa; };
|>  > sturct Professor { int peckingOrder; float salary; };
|>  > int main () {
|>  >         Student s;
|>  >         Professor p;
|>  >         unsigned char* ps(suitable_cast<unsigned char*>(&s));
|>  >         unsigned char* pp(suitable_cast<unsigned char*>(&p));
|>  >         unsigned char* const pse(ps + sizeof(Student));
|>  >         while (ps != pse)
|>  >                 *pp++ = *ps++;
|>  >         int* psid(suitable_cast<int*>(&s));
|>  >         Professor& rp(suitable_cast<Professor&>(p.peckingOrder));  // ??
|>  >         unsigned char buffer[sizeof(Student)];
|>  >         pp = suitable_cast<unsigned char*>(&p);
|>  >         for (int x = 0; x < sizeof(Professor); ++ x)
|>  >                 buffer[x] = pp[x];
|>  >         cout << hex;
|>  >         for (ps = suitable_cast<unsigned char*>(&s); ps != pse; ++ ps)
|>  >                 cout << static_cast<int>(*ps) << ' ';
|>  >         cout << endl;
|>  >         }
|>  >
|>  > My problem is finding suitable_cast.  It is easy to eliminate
|>  > const_cast, dynamic_cast and static_cast since these things are
|>  > not on the lists of doable things.  I can't use reinterpret_cast
|>  > because it is not portable and it has been pointed out that the
|>  > sizeof(char*) is not the same as sizeof(int*) on some implementations.
|>  >
|>  > What do I use for sutiable_cast?
|>
|>  None, and it was the point of one of my posting in this newsgroup;

I think that in this case, reinterpret_cast IS portable. At least, the
old style cast was portable in C, and an old style cast here has the
semantics of a reinterpret_cast, so it "should" be portable if C
compatibility is to be maintain.

I don't have my C standard here to argue why it was defined in C, but I
know that the reasoning was rather indirect, and that in fact, there was
an "request for interpretation" ruling to clarify it.

Basically, however, there are two points:

1. A void* must be able to hold any pointer type without loss of value.
For historical reasons, this guarantee is extended to pointers to
character types.  So the "reinterpret_cast" cannot be value-losing in
this case.

2. According to the interpretation ruling in C, "unsigned char" is a
special type, which is guaranteed to access raw memory, and every bit of
it. Note that this guarantee is ONLY extended to "unsigned char"; a
"signed char" is allowed, e.g. under 1's complement to convert negative
0's (0xff) to positive ones on loading or storing.  And a plain char is
allowed to be signed.

Concerning the above:

1. It is based on my understanding of C, and not drawn from the current
draft.

2. It is from memory; I have neither the C standard nor the
interpretation ruling here to look at.  I believe that what I have said
describes the impact of the ruling correctly, but I could be wrong.  And
it almost certainly wasn't in the words I've used.

I think that the first point is guaranteed by 5.2.10/7 (conversion
cannot be lossy if the alignment requirements of the destination pointer
are not greater than those of the source): one can deduit that the
alignment requirements cannot be greater than the size (as returned by
sizeof), and "sizeof( unsigned char ) == 1" by definition.  From this,
"unsigned char" may not have alignment requirements, so casting to it
cannot be lossy.

I'm not sure that the draft addresses the second point.  I would be very
pleased if someone could assure me that an "unsigned char*" is required
to access "raw memory", according to the draft.  I would be even happier
if they could point out where in the draft this is guaranteed.  (Or is
it due to the inclusion of the C standard by reference?)

--
James Kanze      home:     kanze@gabi-soft.fr        +33 (0)1 39 55 85 62
                 office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
     -- Conseils en informatique industrielle --
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: jpotter@falcon.lhup.edu (John E. Potter)
Date: 1997/03/12
Raw View
James Kanze (james-albert.kanze@vx.cit.alcatel.fr) wrote:
> Valentin Bonnard <bonnardv@pratique.fr> writes:
> |>  jpotter@falcon.lhup.edu (John E. Potter) wrote:
> |>  > Various parts of the draft authorize the following, I think.

 [ examples of doable things which have no simple cast ]

> |>  > My problem is finding suitable_cast.  It is easy to eliminate
> |>  > const_cast, dynamic_cast and static_cast since these things are
> |>  > not on the lists of doable things.  I can't use reinterpret_cast
> |>  > because it is not portable.

> |>  > What do I use for sutiable_cast?

> |>  None, and it was the point of one of my posting in this newsgroup;

> I think that in this case, reinterpret_cast IS portable. At least, the
> old style cast was portable in C, and an old style cast here has the
> semantics of a reinterpret_cast, so it "should" be portable if C
> compatibility is to be maintain.

Steve Clamage has pointed out many times that reinterpret_cast is "never"
portable.  I agree that it "should" be portable; however, IMHO there
should be a means in a standard to do things which are required by a
standard to be doable.

> Basically, however, there are two points:

> 1. A void* must be able to hold any pointer type without loss of value.
> For historical reasons, this guarantee is extended to pointers to
> character types.  So the "reinterpret_cast" cannot be value-losing in
> this case.

Actually (3.9.2/4), void* is required to be like char*; and unlike void*,
char* is dereferencable.  So reinterpret_cast cannot be value-losing;
however, there is no requirement that the cast be dereferencable.  It
must be possible to return the value if recast to the original type,
but nothing is said about what can be done with the other type.  It is
possible to tag the pointer to indicate that it is value preserving but
not usable, I guess.

> 2. According to the interpretation ruling in C, "unsigned char" is a
> special type, which is guaranteed to access raw memory, and every bit of
> it. Note that this guarantee is ONLY extended to "unsigned char"; a
> "signed char" is allowed, e.g. under 1's complement to convert negative
> 0's (0xff) to positive ones on loading or storing.  And a plain char is
> allowed to be signed.

The C standard is a normative reference (1.2); however, on reading it
again, I think that it only says that any reference to it within the
C++ standard is normative, not that it is included in its entirety.  The
differences (C2) are given in an informative way.  The C standard is
referenced in many places, in particular, with respect to the memory
model.

In C++, an object may be accessed (3.10/15) via an lvalue of type unsigned
char or char.  However, I find no way to obtain an unsigned char* or a
char* which points to an object in a portable way.  Raw memory may be
accessed via memcpy (3.9/2) as an example; however, I think that
would apply as well to unsigned char*.  Can I write myMemcpy:

  void myMemcpy (void* dest, void* source, int bytes) {
   unsigned char* d(static_cast<unsigned char*>(dest));
   unsigned char* s(static_cast<unsigned char*>(source));
   for (; bytes > 0; -- bytes)
    *d++ = *s++;
      }

The standard conversion to void* in calling myMemcpy must point to the
same object; so, I would assume that the static_cast from void* must
also be value preserving.  This leads to the conclusion that the
suitable_cast that I am looking for is spelled

  static_cast<desired*>(static_cast<void*>(somePtr));

as long as I stick to desired == typeof(somePtr), desired is
char or unsigned char, or desired/typeof(somePtr) are POD struct and
first member in either order(9.2/17).  Disgusting things to code though.

> Concerning the above:

 [ disclaimers ]

> I think that the first point is guaranteed by 5.2.10/7 (conversion
> cannot be lossy if the alignment requirements of the destination pointer
> are not greater than those of the source): one can deduit that the
> alignment requirements cannot be greater than the size (as returned by
> sizeof), and "sizeof( unsigned char ) == 1" by definition.  From this,
> "unsigned char" may not have alignment requirements, so casting to it
> cannot be lossy.

I think that from array requirements that a stronger deduction can be made:

  sizeof(X) % alignment(X) == 0

which includes your <=.  But 5.2.10/7 does not assure that the
value preserving pointer can be used.  It explicitely avoids any
statement about use of the cast type.  Other paragraphs explicitely
make use of the cast pointer in those cases undefined.

> I'm not sure that the draft addresses the second point.  I would be very
> pleased if someone could assure me that an "unsigned char*" is required
> to access "raw memory", according to the draft.  I would be even happier
> if they could point out where in the draft this is guaranteed.  (Or is
> it due to the inclusion of the C standard by reference?)

See above.

The platforms on which I work have no alignment requirements; however,
the compilers do.  One of the things which I do, knowing that it is
not portable, is use unaligned longs.  Assume size/allign for short 2/2,
long 4/4, array x/4.

  short data[36];
  long stuff;
  *reinterpret_cast<long*>(data + 33) = stuff;

This works for all of the implementations used, but it is clearly not
something which is portable.  On another platform, it could core dump
from an addressing trap.  It just happens that on these platforms the
undefined behavior is what I want.  I would not like to use the same
notation for things which are required to be portable.  I could write
the above portably as

 memcpy(data + 33, stuff, sizeof(long));

In the sence that it will do what I said.  If sizeof(long) != 2 *
sizeof(short), it may not do what I expected.

How portable does this look?

 someOfstream.write(reinterpret_cast<char*>(data), sizeof(data));

It is suppossed to be portable, isn't it?

I have the feeling that in the beginning, static_cast may have been
intended to be totally safe.  As it stands now, it includes the things
which can be reasonably safe like casting down a hierarchy when one
"knows" that it is possible and casting from void* to what one "knows"
is reasonable.  I think that it would be reasonable to include the
suitable_cast items in static_cast.  Anything* to char* or unsigned char*,
POD struct* to/from first member*.  And for references.  Then
reinterpret_cast could be the implementation defined, non-portable
cast that we all know it is.  And the draft required doable things
would be static_cast, dynamic_cast, const_cast or old style.

My thoughts, anyone's comments?
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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: schwab@issan.informatik.uni-dortmund.de (Andreas Schwab)
Date: 1997/03/12
Raw View
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:

|> Basically, however, there are two points:

|> 1. A void* must be able to hold any pointer type without loss of value.

I think that should be *data* pointer type.  A cast between function and
data pointer types is undefined.
--
Andreas Schwab                                      "And now for something
schwab@issan.informatik.uni-dortmund.de              completely different"
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: jpotter@falcon.lhup.edu (John E. Potter)
Date: 1997/03/06
Raw View
Various parts of the draft authorize the following, I think.

#include <iostream.h>
struct Student { int id; float gpa; };
sturct Professor { int peckingOrder; float salary; };
int main () {
 Student s;
 Professor p;
 unsigned char* ps(suitable_cast<unsigned char*>(&s));
 unsigned char* pp(suitable_cast<unsigned char*>(&p));
 unsigned char* const pse(ps + sizeof(Student));
 while (ps != pse)
  *pp++ = *ps++;
 int* psid(suitable_cast<int*>(&s));
 Professor& rp(suitable_cast<Professor&>(p.peckingOrder));  // ??
 unsigned char buffer[sizeof(Student)];
 pp = suitable_cast<unsigned char*>(&p);
 for (int x = 0; x < sizeof(Professor); ++ x)
  buffer[x] = pp[x];
 cout << hex;
 for (ps = suitable_cast<unsigned char*>(&s); ps != pse; ++ ps)
  cout << static_cast<int>(*ps) << ' ';
 cout << endl;
 }

My problem is finding suitable_cast.  It is easy to eliminate
const_cast, dynamic_cast and static_cast since these things are
not on the lists of doable things.  I can't use reinterpret_cast
because it is not portable and it has been pointed out that the
sizeof(char*) is not the same as sizeof(int*) on some implementations.

What do I use for sutiable_cast?

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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1997/03/09
Raw View
jpotter@falcon.lhup.edu (John E. Potter) wrote:
> Various parts of the draft authorize the following, I think.
>
> #include <iostream.h>
> struct Student { int id; float gpa; };
> sturct Professor { int peckingOrder; float salary; };
> int main () {
>         Student s;
>         Professor p;
>         unsigned char* ps(suitable_cast<unsigned char*>(&s));
>         unsigned char* pp(suitable_cast<unsigned char*>(&p));
>         unsigned char* const pse(ps + sizeof(Student));
>         while (ps != pse)
>                 *pp++ = *ps++;
>         int* psid(suitable_cast<int*>(&s));
>         Professor& rp(suitable_cast<Professor&>(p.peckingOrder));  // ??
>         unsigned char buffer[sizeof(Student)];
>         pp = suitable_cast<unsigned char*>(&p);
>         for (int x = 0; x < sizeof(Professor); ++ x)
>                 buffer[x] = pp[x];
>         cout << hex;
>         for (ps = suitable_cast<unsigned char*>(&s); ps != pse; ++ ps)
>                 cout << static_cast<int>(*ps) << ' ';
>         cout << endl;
>         }
>
> My problem is finding suitable_cast.  It is easy to eliminate
> const_cast, dynamic_cast and static_cast since these things are
> not on the lists of doable things.  I can't use reinterpret_cast
> because it is not portable and it has been pointed out that the
> sizeof(char*) is not the same as sizeof(int*) on some implementations.
>
> What do I use for sutiable_cast?

None, and it was the point of one of my posting in this newsgroup;
I also restated that in two followup ('Casts: what are the
differences' and to the thread about static_cast).

I never got any answers on this topic; I hope your post will
get some; Steve Clamage indirectly answered that as a
followup to James Kanze saying that implementors should
make reinterpret_cast to work in this case, just as a
correct implementation should compile programs longer
then 5 lines (IMO there aren't required to accept them).

IMO the requirement on reinterpret_cast should be stronger.
My problem is that I only know 'normal' processors were
pointers are all represented the same and I am  not sure what
the restrictions should be:

(a) reinterpret_cast preserve the representation (the bytes)

(b) reinterpret_cast preserve the value (obtained with
    convert<void*>)


(c) o reinterpret_cast<[signess] char*> return a pointer to
      the storage of the variable 'suitable for direct
      manipulation'

    o reinterpret_cast<T*> (p) return a pointer to the first
      member of the struct pointed to by p (if it's the case)
      or to any member of an union pointed to by p (recursivly)
      if the member is of type T

(a) seem way too strong on weird processors and isn't much more
usefull than (b).

(b) seem correct to me (also something is needed to tell that
it's the suitable cast the DWP is talking about)

(c) is what the minimum I would expect from a very weird
implemention which claim to be conformant, but I would prefer
the DWP to contain (b); I'm sure such a small change can be
accepted now

I'd like to here opinions about (b) and (c).

--

Valentin Bonnard
mailto:bonnardv@pratique.fr
http://www.pratique.fr/~bonnardv (Informations sur le C++ en Francais)
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]