Topic: Interpretation of old-style casts in templates
Author: ken@digitas.org (Ken Shan)
Date: 1996/12/01 Raw View
I know this is not terribly important since it's deprecated anyway,
but I'm just curious...
struct A { int a; };
struct B { int b; };
struct C: A, B { };
template <class T>
B *f(T t)
{
return (B *)t;
}
// ...
A *pa;
B *pb;
C *pc;
f(pa); // obviously reinterpret_cast<B *>(pa)
f(pb); // obviously just pb
f(pc); // what's the interpretation for this?
I.e., should f(pc) be equivalent to reinterpret_cast<B *>(pc) (to be
consistent with the interpretation if T were any random type) or
static_cast<B *>(pc) (what would result if T is replaced with C *
throughout the definition of f())?
--
blue | Ken; Shan, Chung-chieh; Sian7, Tiong1-kiat8; ken@digitas.harvard.edu.
() | Your code today becomes the mind tomorrow: Your plan its means,
/\ | your dream its ends, your ideal its elegance. Hack on.
---
[ 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: Alexandre Oliva <oliva@dcc.unicamp.br>
Date: 1996/12/02 Raw View
Ken Shan writes:
> struct A { int a; };
> struct B { int b; };
> struct C: A, B { };
> template <class T>
> B *f(T t)
> {
> return (B *)t;
> }
> C *pc;
> f(pc); // what's the interpretation for this?
> I.e., should f(pc) be equivalent to reinterpret_cast<B *>(pc) (to be
> consistent with the interpretation if T were any random type) or
> static_cast<B *>(pc) (what would result if T is replaced with C *
> throughout the definition of f())?
There's no reason to believe (B*) should be equivalent to
reinterpret_cast<B*>. If you want a reinterpret_cast or a
static_cast, write this in the program explicitly. Only use an
old-style cast if you wish the compiler to do the best it can to do a
safe conversion.
--
Alexandre Oliva
mailto:oliva@dcc.unicamp.br
Universidade Estadual de Campinas, SP, Brasil
[ 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: ken@digitas.org (Ken Shan)
Date: 1996/12/03 Raw View
Alexandre Oliva (oliva@dcc.unicamp.br) wrote:
> There's no reason to believe (B*) should be equivalent to
> reinterpret_cast<B*>. If you want a reinterpret_cast or a
> static_cast, write this in the program explicitly. Only use an
> old-style cast if you wish the compiler to do the best it can to do a
> safe conversion.
I know I shouldn't use old-style casts, and I don't; I'm just
wondering what the current draft standard specifies...
--
blue | Ken; Shan, Chung-chieh; Sian7, Tiong1-kiat8; ken@digitas.harvard.edu.
() | Your code today becomes the mind tomorrow: Your plan its means,
/\ | your dream its ends, your ideal its elegance. Hack on.
---
[ 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: bradds@concentric.net (Bradd W. Szonye)
Date: 1996/12/04 Raw View
Ken Shan <ken@digitas.org> wrote in article
<57revl$olm@decaxp.harvard.edu>...
> I know this is not terribly important since it's deprecated anyway,
> but I'm just curious...
Are old-style casts deprecated? I didn't think they were yet.
> struct A { int a; };
> struct B { int b; };
> struct C: A, B { };
>
> template <class T> B* f(T t)
> { return (B*) t; }
>
> A *pa; B *pb; C *pc;
> f(pa); // obviously reinterpret_cast<B *>(pa) [not quite right]
> f(pb); // obviously just pb
> f(pc); // what's the interpretation for this?
>
> I.e., should f(pc) be equivalent to reinterpret_cast<B *>(pc) (to be
> consistent with the interpretation if T were any random type) or
> static_cast<B *>(pc) (what would result if T is replaced with C *
> throughout the definition of f())?
I think you misinterpreted Alexandre Oliva's reply to your article. His
point wasn't so much that you shouldn't use old-style casts as much as that
they don't do exactly what you assumed in your article. Old-style casts
don't necessarily mean reinterpret_cast<>; but they might accomplish the
same thing in some cases.
The fact that the old-style cast occurs in a template means nothing. The
three instantiations of your template function contain the equivalent of
A* t; return (B*) t;
B* t; return (B*) t;
C* t; return (B*) t;
These old-style casts behave they same way they always have in C++. Since
A* and B* are unrelated static types, the bit-pattern of one is merely
reinterpreted as the other, with implementation-defined effects. Since B*
and B* are the same type, the second cast performs no operation. Since C*
and B* are related to each other by derivation, the third cast performs a
conversion to base-class subobject (which is an implicit conversion in that
situation anyway). If B were derived from D and you added
D* t; return (B*) t;
then the cast would perform a (static) downcast from D* to B*, whether the
object is really a B or not. Notice that the meaning of the cast changes
depending on the types in the instantiation. That's a possible way to
confuse maintainers of code, but it might be just what you wanted.
Keep in mind that each of the new-style casts has a particular, limited
operation, with very little room for interpretation on the compiler's part.
Old-style casts are a sort of "best effort" by the compiler to figure out
what you meant to do. Thus Alexandre's statement to use reinterpret_cast<>
when you need that and to use old-style casts when you need those. Also
keep in mind that there are a couple of unsafe casts (for example, between
private base classes and derived classes) that _only_ old-style casts can
accomplish.
--
Bradd W. Szonye
bradds@concentric.net
http://www.concentric.net/~bradds
[ 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: Alexandre Oliva <oliva@dcc.unicamp.br>
Date: 1996/12/04 Raw View
Ken Shan writes:
> Alexandre Oliva (oliva@dcc.unicamp.br) wrote:
>> There's no reason to believe (B*) should be equivalent to
>> reinterpret_cast<B*>. If you want a reinterpret_cast or a
>> static_cast, write this in the program explicitly. Only use an
>> old-style cast if you wish the compiler to do the best it can to do a
>> safe conversion.
> I know I shouldn't use old-style casts, and I don't; I'm just
> wondering what the current draft standard specifies...
The standard specifies that the following alternatives will be tried,
in this order, and the first one to succeed will be taken:
--a const_cast (_expr.const.cast_),
--a static_cast (_expr.static.cast_),
--a static_cast followed by a const_cast,
--a reinterpret_cast (_expr.reinterpret.cast_), or
--a reinterpret_cast followed by a const_cast,
(from [expr.cast] paragraph 5)
--
Alexandre Oliva
mailto:oliva@dcc.unicamp.br
Universidade Estadual de Campinas, SP, Brasil
[ 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 ]