May 13, 2008 Re: safer casts - take II | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Yigal Chripun | Yigal Chripun wrote: > since the other thread got completely off-topic and lost any connection > to the original discussion, here's a new clean thread, that will > hopefully summarize the previous discussion and present the latest > proposal so that hopefully more people join the debate without the need > to go through all the previous posts (164 posts!). > > Here goes: > > the proposal is for a safer cast that will _replace_ the current cast. > this is important both for a consistent syntax and to prevent subverting > the system with the old style cast. > > there are there forms of cast: > (a) cast(T)something > (b) cast!(T)something No no. "super cast(T)something" is what you're looking for. :-) [1] > (c) reinterpret_cast!(T) Seriously, though, it sounds good to me. My initial impression was that basically we needed just one alternative form of cast. Leave cast(T) for the "yes I'm casting but it's not a big deal" forms, and make some new form for the "Lookout! Crazy guy with a cast who's not afraid to use it, here!" And that's pretty much what you folks seem to have settled on. (Discounting the third form, reinterpret_cast, since it's just a library function -- but a good one to have, I'll agree) [1] (For those who don't recall "invariant" was slated to be called "super const" for a while...) --bb | |||
May 13, 2008 Re: safer casts - take II | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Yigal Chripun | Long ago in one of the const threads, a few people settled on cast(break const) for what I think you're calling cast!(T). I like that better than using template syntax to mean less safe.
Yigal Chripun Wrote:
> since the other thread got completely off-topic and lost any connection to the original discussion, here's a new clean thread, that will hopefully summarize the previous discussion and present the latest proposal so that hopefully more people join the debate without the need to go through all the previous posts (164 posts!).
>
> Here goes:
>
> the proposal is for a safer cast that will _replace_ the current cast. this is important both for a consistent syntax and to prevent subverting the system with the old style cast.
>
> there are there forms of cast:
> (a) cast(T)something
> (b) cast!(T)something
> (c) reinterpret_cast!(T)
>
> there is no need for language support for (c) since this can be implemented via a union and this is exactly what this library template does. the only reason for this is to have a standardized name. unless the user really knows what he's doing this should be avoided, since this is the most dangerous form of cast.
>
> goals of this design:
> 1. you can search/grep for all casts in your code.
> 2. constancy is cast explicitly so no more casting an invariant T to a
> mutable U in one cast. this prevents bugs.
>
> (a) will do would you'll expect in the common case. while (b) is for
> more "dangerous" casts. it can also be defined in all forms
> (implicit/explicit) by the user while (b) isn't.
>
> if T is a class then (a) uses RTTI cast (down casting) or a user defined
> conversion, otherwise (a) will do plain conversions like the current
> cast does.
> (b) is used for constancy casts and the specific use case of casting
> pointers to void. (more specific cases could be added in the future)
>
> for c++ people this translates to:
> (a) (T is a class) ? dynamic_cast : static_cast
> (b) const_cast
> (c) reinterpret_cast implemented in library
>
> also note that cast(T) for classes will return null on failure just
> like in current D.
>
> questions?
| |||
May 13, 2008 Re: safer casts - take II | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jason House | Jason House wrote:
> Long ago in one of the const threads, a few people settled on
> cast(break const) for what I think you're calling cast!(T). I like
> that better than using template syntax to mean less safe.
>
That's a good point I want to address:
initially this is exactly what I proposed, albeit with some minor
changes to syntax. [that was: cast(!const) where the ! was meant to be a
"not" similar to your break.
the problem is that it's not flexible enough.
how do you cast the following:
const(invariant(C)*)* ==> const(C*)* ?
this is a contrived example of course, but with cast!(T) you can just use:
auto newVal = cast!(const(C*)*)oldVal;
this works since this passes the following simple test:
if you remove all invariant/const modifiers in both the source and
target types you need to get the exact same type. this is to make sure
you only change constancy and not the type. in the above case you'll
get: ((C)*)* ==> (C*)* and those two are identical.
this only changes constancy and thus legal. had you tried to also change
type you'd get an exception.
with cast(break const) or cast(!const) this is not possible with just one cast. that kind of shortcut may be considered as well, but since you can always just specify the new constancy of the type this adds very little benefit but adds another syntax rule to the language. I think that Walter probably won't agree to add such a syntax rule and bloat the language without proper justification. with this I 100% sure that I prefer the minimalist approach and do not want to include this in the proposal.
feel free to discuss this issue too and suggest use-cases where you think this syntax is needed.
| |||
May 13, 2008 Re: safer casts - take II | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Yigal Chripun | Note that in addition, the ! form would also be the one to use for:
void[] p;
T[] q = cast!(T[])p;
So it's not /just/ removal of const that "danger cast" is for. It's also for casting from void to non-void. For that reason, calling it "break const" would be highly counterintuitive.
| |||
May 14, 2008 Re: safer casts - take II | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Yigal Chripun Attachments: | Yigal Chripun wrote:
> there are there forms of cast:
> (a) cast(T)something
> (b) cast!(T)something
> (c) reinterpret_cast!(T)
So, for example, given the following definitions:
class A {…}
class B : A {…}
class C : A {…}
class D {…}
we can write:
const A ac;
auto a = cast!(A)a;
and:
B b0;
auto a = cast(A)b0;
auto b = cast(B)a; // should succeed
auto c = cast(C)a; // c is null
and:
A a;
auto d = reinterpret_cast(D)a; // legal but unpredictable
Are these all the intended uses?
—Joel S.
| |||
May 15, 2008 Re: safer casts - take II | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Joel C. Salomon | On 14/05/2008, Joel C. Salomon <joelcsalomon@gmail.com> wrote:
> Are these all the intended uses?
Yep.
| |||
June 10, 2008 Re: safer casts - take II | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Yigal Chripun | Sorry I'm late.
First of all, I agree with the general principle that D's cast system should be more safe. But there are some aspects of your proposal I don't agree.
First is the cast(...) vs. cast!(...) syntax. I strongly disagree with it, I don't think such constructs should have such a similar syntax, particularly sharing the same base name, yet one looking like a function call, and the other like a template. I know that the rationale for cast!(...) would be to indicate that this is a compile time operation, unlike cast(...) but I still don't like it.
But even further than that, I agree with Jason, in that the constancy cast construct should not require the type to cast, but just the const modifiers. That is, there should only be the forms "cast(const)", "cast(invariant)", and "cast(!const)". (Altough cast(!const) should really be called cast(mutable) , but that's another issue, about keywords)
Some points were raised against it:
Yigal Chripun wrote:
> Jason House wrote:
>> Long ago in one of the const threads, a few people settled on
>> cast(break const) for what I think you're calling cast!(T). I like
>> that better than using template syntax to mean less safe.
>>
>
> That's a good point I want to address:
> initially this is exactly what I proposed, albeit with some minor
> changes to syntax. [that was: cast(!const) where the ! was meant to be a
> "not" similar to your break.
>
> the problem is that it's not flexible enough.
> how do you cast the following:
> const(invariant(C)*)* ==> const(C*)* ?
> this is a contrived example of course, but with cast!(T) you can just use:
> auto newVal = cast!(const(C*)*)oldVal;
> this works since this passes the following simple test:
> if you remove all invariant/const modifiers in both the source and
> target types you need to get the exact same type. this is to make sure
> you only change constancy and not the type. in the above case you'll
> get: ((C)*)* ==> (C*)* and those two are identical.
> this only changes constancy and thus legal. had you tried to also change
> type you'd get an exception.
>
> with cast(break const) or cast(!const) this is not possible with just
> one cast. that kind of shortcut may be considered as well, but since you
> can always just specify the new constancy of the type this adds very
> little benefit but adds another syntax rule to the language. I think
> that Walter probably won't agree to add such a syntax rule and bloat the
> language without proper justification. with this I 100% sure that I
> prefer the minimalist approach and do not want to include this in the
> proposal.
>
> feel free to discuss this issue too and suggest use-cases where you
> think this syntax is needed.
Well, it's true that you couldn't directly do that case "with just one cast", but one could define a template that did it with just one call:
const(invariant(C)*)* foo;
auto bar = const_cast!(const(C*)*, foo);
So I don't think that would be a problem, right?
Janice Caron wrote:
> Note that in addition, the ! form would also be the one to use for:
>
> void[] p;
> T[] q = cast!(T[])p;
>
> So it's not /just/ removal of const that "danger cast" is for. It's
> also for casting from void to non-void. For that reason, calling it
> "break const" would be highly counterintuitive.
reinterpret_cast would serve that purpose just fine, wouldn't it?
--
Bruno Medeiros - Software Developer, MSc. in CS/E graduate
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply