www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - cast()x - a valid expression?

reply KennyTM~ <kennytm gmail.com> writes:
While checking the Phobos source I've found an interesting expression

       cast()(result[i]) = to!(E)(e);

The 'cast()' means 'cast to mutable', e.g.

       class S {}
       void g(S x) {}
       void main() {
          const S s;
          g(cast()s);
       }

But this is not documented in the D spec (CastParam cannot be empty). Is 
this an "accept-invalid" bug, or just a feature not yet documented?
Jun 01 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
It seems to do even more than that:

    int a;
    const int b;
    immutable int c;
    shared int d;
    shared(const int) e;

    static assert(is(typeof(cast()a) == int));
    static assert(is(typeof(cast()b) == int));
    static assert(is(typeof(cast()c) == int));
    static assert(is(typeof(cast()d) == int));
    static assert(is(typeof(cast()e) == int));

Talk about stealing the storm from std.traits.Unqual..

On 6/1/11, KennyTM~ <kennytm gmail.com> wrote:
 While checking the Phobos source I've found an interesting expression

        cast()(result[i]) = to!(E)(e);

 The 'cast()' means 'cast to mutable', e.g.

        class S {}
        void g(S x) {}
        void main() {
           const S s;
           g(cast()s);
        }

 But this is not documented in the D spec (CastParam cannot be empty). Is
 this an "accept-invalid" bug, or just a feature not yet documented?

Jun 01 2011
next sibling parent reply KennyTM~ <kennytm gmail.com> writes:
On Jun 2, 11 04:05, Steven Schveighoffer wrote:
 On Wed, 01 Jun 2011 15:38:32 -0400, Andrej Mitrovic
 <andrej.mitrovich gmail.com> wrote:

 It seems to do even more than that:

 int a;
 const int b;
 immutable int c;
 shared int d;
 shared(const int) e;

 static assert(is(typeof(cast()a) == int));
 static assert(is(typeof(cast()b) == int));
 static assert(is(typeof(cast()c) == int));
 static assert(is(typeof(cast()d) == int));
 static assert(is(typeof(cast()e) == int));

 Talk about stealing the storm from std.traits.Unqual..

 On 6/1/11, KennyTM~ <kennytm gmail.com> wrote:
 While checking the Phobos source I've found an interesting expression

 cast()(result[i]) = to!(E)(e);

 The 'cast()' means 'cast to mutable', e.g.

 class S {}
 void g(S x) {}
 void main() {
 const S s;
 g(cast()s);
 }

 But this is not documented in the D spec (CastParam cannot be empty). Is
 this an "accept-invalid" bug, or just a feature not yet documented?


It gets even better: char[] x = "abc".dup; assert(is(typeof(cast(const)x) == const(char[])); I think you may have found a "bug" that should be a feature. It's like dmd is organically growing features that we might need ;) Is this software evolution? Scary! When will dmd decide that human life is a disease to be eradicated? When will the world be dominated by constinators?!!! I fear for my children. All kidding aside, I actually think the syntax makes sense. You are adding/removing modifiers, so just leave the type out of it. The only drawback is, you can't do a cast directly to a tail-const array, but that's not a huge deal, since const(T[]) implicitly casts to const(T)[]. I dub this feature "Type Modifier Casting". -Steve

cast(const), cast(immutable) etc are documented. cast() is not. See http://d-programming-language.org/expression.html#CastExpression
Jun 01 2011
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
On 01/06/2011 21:51, Steven Schveighoffer wrote:
 On Wed, 01 Jun 2011 16:38:42 -0400, KennyTM~ <kennytm gmail.com> wrote:

 cast(const), cast(immutable) etc are documented. cast() is not. See
 http://d-programming-language.org/expression.html#CastExpression


What is that site? A reference for how the compiler actually behaves, as opposed to the spec?
 :O

 Of course, by documented, it shows the cast in the grammar (BTW, why the
separate rule for
 cast(Type) when CastParam can be Type?), but not in the text. I almost never
read the
 grammar unless I'm confused by the docs.

 This is almost as good as const_cast, although it seems too easy to screw up
and remove
 const when you don't want to.

And it's a puzzling notation. Nobody would guess what it means. As such, it looks like a bug that the compiler accepts the code. See also previous discussions about making casting away const/immutable explicit: http://tinyurl.com/4x7wpy9 http://tinyurl.com/4xotq3o Stewart.
Jun 03 2011
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Steven Schveighoffer" <schveiguy yahoo.com> wrote in message 
news:op.vwex37voeav7ka localhost.localdomain...
 On Wed, 01 Jun 2011 15:38:32 -0400, Andrej Mitrovic 
 <andrej.mitrovich gmail.com> wrote:

 It seems to do even more than that:

     int a;
     const int b;
     immutable int c;
     shared int d;
     shared(const int) e;

     static assert(is(typeof(cast()a) == int));
     static assert(is(typeof(cast()b) == int));
     static assert(is(typeof(cast()c) == int));
     static assert(is(typeof(cast()d) == int));
     static assert(is(typeof(cast()e) == int));

 Talk about stealing the storm from std.traits.Unqual..

 On 6/1/11, KennyTM~ <kennytm gmail.com> wrote:
 While checking the Phobos source I've found an interesting expression

        cast()(result[i]) = to!(E)(e);

 The 'cast()' means 'cast to mutable', e.g.

        class S {}
        void g(S x) {}
        void main() {
           const S s;
           g(cast()s);
        }

 But this is not documented in the D spec (CastParam cannot be empty). Is
 this an "accept-invalid" bug, or just a feature not yet documented?


It gets even better: char[] x = "abc".dup; assert(is(typeof(cast(const)x) == const(char[])); I think you may have found a "bug" that should be a feature. It's like dmd is organically growing features that we might need ;) Is this software evolution? Scary! When will dmd decide that human life is a disease to be eradicated? When will the world be dominated by constinators?!!! I fear for my children. All kidding aside, I actually think the syntax makes sense. You are adding/removing modifiers, so just leave the type out of it. The only drawback is, you can't do a cast directly to a tail-const array, but that's not a huge deal, since const(T[]) implicitly casts to const(T)[]. I dub this feature "Type Modifier Casting".

It's nice in a way, but it's all based on the way cast handles modifiers. And I've always been a bit unconfortable with how that's handled (In fact, I was just thinking about this yesterday). Specifically, it seems extremely bad that it's so incredibly easy to accidentaly cast away things like const and immutable: For example, if I know I have an array of uint's, and I want to deal with the individual bytes, it's perfectly safe and sensible to cast it to a ubyte[] (a long as you factor in endianness, of course). So, you do "cast(ubyte[])myArray". But, OOPS!!: If myArray happened to be immutable, then merely trying to cast the type has inadvertantly cast-away immutable. Not good! Casting away const/immutable really, really should have to be explict. Of course, you can probably use some fancy helper templates to make sure you preserve all modifiers. But needing to do so is just asking for mistakes: it seems like a huge violation of "make the right way easy, and the wrong way hard".
Jun 01 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 Personally, I find 
 how C++ created multiple types of cast (include const_cast) _highly_ annoying 
 and generally useless, and I'm _very_ glad that D didn't do anything of the 
 sort.

Conflating all casts in a single syntax makes the D language look a bit simpler, but it also reduces the amount of expressivity and I suspect it may lead to some bugs (here Unqual helps). Changing the const state of a type is often orthogonal to changing its data type. Thankfully D templates make it easy enough to build new types of cast. Time ago I have proposed a staticObjCast! for object references that performs some static sanity tests too. Unqual!() is another kind of cast, but it's a bit blunt. std.conv.to! is another kind of cast, that performs more complex conversions too. I am proposing to use to! for safe enum conversions too. A staticCast! that uses a locally defined enum sounds useful and safe. Bye, bearophile
Jun 01 2011
prev sibling next sibling parent Jesse Phillips <jessekphillips+D gmail.com> writes:
Nick Sabalausky Wrote:

 Of course, you can probably use some fancy helper templates to make sure you 
 preserve all modifiers. But needing to do so is just asking for mistakes: it 
 seems like a huge violation of "make the right way easy, and the wrong way 
 hard".

Relevant: http://d.puremagic.com/issues/show_bug.cgi?id=5307 Using to!() should not allow removal of qualifiers
Jun 01 2011
prev sibling parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
On 01/06/2011 22:12, Jonathan M Davis wrote:
 It's nice in a way, but it's all based on the way cast handles modifiers.
  And I've always been a bit unconfortable with how that's handled (In fact,
  I was just thinking about this yesterday). Specifically, it seems
  extremely bad that it's so incredibly easy to accidentaly cast away things
  like const and immutable:

  For example, if I know I have an array of uint's, and I want to deal with
  the individual bytes, it's perfectly safe and sensible to cast it to a
  ubyte[] (a long as you factor in endianness, of course). So, you do
  "cast(ubyte[])myArray". But, OOPS!!: If myArray happened to be immutable,
  then merely trying to cast the type has inadvertantly cast-away immutable.
  Not good! Casting away const/immutable really, really should have to be
  explict.

  Of course, you can probably use some fancy helper templates to make sure
  you preserve all modifiers. But needing to do so is just asking for
  mistakes: it seems like a huge violation of "make the right way easy, and
  the wrong way hard".


you're only supposed to use it when you know what you're doing when you use it. And if there's really any possibility that you're dealing with immutable, perhaps you should be casting to const rather than mutable. Personally, I find how C++ created multiple types of cast (include const_cast)_highly_ annoying and generally useless, and I'm_very_ glad that D didn't do anything of the sort. - Jonathan M Davis

"you're only supposed to use it when you know what you're doing when you use it" Well, that's kinda the requirement for any feature, isn't it?... :P Well, kinda, I do know what you mean. Yes, one needs to properly learn how cast() works, but that doesn't mean it would not be better for the feature to be designed in a way that is easier to learn (and just as powerful to use), or actually, it doesn't mean that even if you do know how cast() works, that you are not still likely to make a mistake when using it. So pretty much I agree with Nick here. I think me and a few others have mentioned it in the past, that the way cast works makes it somewhat easy to trip over one's foot and cast away something that was not intended. This may be a bit more common now and in the future as people use more and more of the newer D modifiers (shared, immutable, etc.). -- Bruno Medeiros - Software Engineer
Jun 02 2011
parent reply Mehrdad <wfunction hotmail.com> writes:
 "you're only supposed to use it when you know what you're doing when you
 use it"
 Well, that's kinda the requirement for any feature, isn't it?... :P
 Well, kinda, I do know what you mean. Yes, one needs to properly learn
 how cast() works, but that doesn't mean it would not be better for the
 feature to be designed in a way that is easier to learn (and just as
 powerful to use), or actually, it doesn't mean that even if you do know
 how cast() works, that you are not still likely to make a mistake when
 using it.
 So pretty much I agree with Nick here. I think me and a few others have
 mentioned it in the past, that the way cast works makes it somewhat easy
 to trip over one's foot and cast away something that was not intended.
 This may be a bit more common now and in the future as people use more
 and more of the newer D modifiers (shared, immutable, etc.).

Yes, let's introduce immutable_cast(), const_cast(), shared_cast(), static_cast(), dynamic_cast(), reinterpret_cast(), sounds like a good idea lol.
Jun 02 2011
parent Mehrdad <wfunction hotmail.com> writes:
== Quote from Mehrdad (wfunction hotmail.com)'s article
 "you're only supposed to use it when you know what you're doing when you
 use it"
 Well, that's kinda the requirement for any feature, isn't it?... :P
 Well, kinda, I do know what you mean. Yes, one needs to properly learn
 how cast() works, but that doesn't mean it would not be better for the
 feature to be designed in a way that is easier to learn (and just as
 powerful to use), or actually, it doesn't mean that even if you do know
 how cast() works, that you are not still likely to make a mistake when
 using it.
 So pretty much I agree with Nick here. I think me and a few others have
 mentioned it in the past, that the way cast works makes it somewhat easy
 to trip over one's foot and cast away something that was not intended.
 This may be a bit more common now and in the future as people use more
 and more of the newer D modifiers (shared, immutable, etc.).


 reinterpret_cast(), sounds like a good idea lol.

Joking aside, I've actually found a few templates to be helpful for casting only one modifier at a time: unconst!(T)(auto ref T value) //Removes const unshared!(T)(auto ref T value) //Remove shared arrcast!(TTo, T)(auto ref T array) //Array cast, keeping const/immutable, doing length divisibility checks, etc. Name is ugly, I couldn't think of anything better Should templates like those be included in std.conv or something?
Jun 02 2011
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/1/2011 1:05 PM, Steven Schveighoffer wrote:
 When will dmd decide that human life is a disease to be eradicated? When will
 the world be dominated by constinators?!!! I fear for my children.

I cannot allow human error to jeopardize the mission.
Jun 01 2011
parent Walter Bright <newshound2 digitalmars.com> writes:
On 6/1/2011 5:46 PM, Andrej Mitrovic wrote:
 Stroustrup: What happen ?
 Meyers: Somebody set up us the bomb.
 Spolsky: We get signal.
 Stroustrup: What !
 Spolsky: Main screen turn on.
 Stroustrup: Itís you !!
 Bright: How are you gentlemen !!
 Bright: All your base are belong to us.
 Bright: You are on the way to destruction.
 Stroustrup: What you say !!
 Bright: You have no chance to survive make your time.
 Bright: Ha ha ha ha Ö

Update - Bright was infected with human error. He has been replaced by the D-9000 computer system.
Jun 01 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 01 Jun 2011 15:38:32 -0400, Andrej Mitrovic  
<andrej.mitrovich gmail.com> wrote:

 It seems to do even more than that:

     int a;
     const int b;
     immutable int c;
     shared int d;
     shared(const int) e;

     static assert(is(typeof(cast()a) == int));
     static assert(is(typeof(cast()b) == int));
     static assert(is(typeof(cast()c) == int));
     static assert(is(typeof(cast()d) == int));
     static assert(is(typeof(cast()e) == int));

 Talk about stealing the storm from std.traits.Unqual..

 On 6/1/11, KennyTM~ <kennytm gmail.com> wrote:
 While checking the Phobos source I've found an interesting expression

        cast()(result[i]) = to!(E)(e);

 The 'cast()' means 'cast to mutable', e.g.

        class S {}
        void g(S x) {}
        void main() {
           const S s;
           g(cast()s);
        }

 But this is not documented in the D spec (CastParam cannot be empty). Is
 this an "accept-invalid" bug, or just a feature not yet documented?


It gets even better: char[] x = "abc".dup; assert(is(typeof(cast(const)x) == const(char[])); I think you may have found a "bug" that should be a feature. It's like dmd is organically growing features that we might need ;) Is this software evolution? Scary! When will dmd decide that human life is a disease to be eradicated? When will the world be dominated by constinators?!!! I fear for my children. All kidding aside, I actually think the syntax makes sense. You are adding/removing modifiers, so just leave the type out of it. The only drawback is, you can't do a cast directly to a tail-const array, but that's not a huge deal, since const(T[]) implicitly casts to const(T)[]. I dub this feature "Type Modifier Casting". -Steve
Jun 01 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 6/1/11, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 It gets even better:

 char[] x = "abc".dup;
 assert(is(typeof(cast(const)x) == const(char[]));

Nothing unusual about that? DMD seems to be full of exciting little easter eggs! It's fun for the whole D family.
Jun 01 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 01 Jun 2011 16:38:42 -0400, KennyTM~ <kennytm gmail.com> wrote:

 On Jun 2, 11 04:05, Steven Schveighoffer wrote:
 On Wed, 01 Jun 2011 15:38:32 -0400, Andrej Mitrovic
 <andrej.mitrovich gmail.com> wrote:

 It seems to do even more than that:

 int a;
 const int b;
 immutable int c;
 shared int d;
 shared(const int) e;

 static assert(is(typeof(cast()a) == int));
 static assert(is(typeof(cast()b) == int));
 static assert(is(typeof(cast()c) == int));
 static assert(is(typeof(cast()d) == int));
 static assert(is(typeof(cast()e) == int));

 Talk about stealing the storm from std.traits.Unqual..

 On 6/1/11, KennyTM~ <kennytm gmail.com> wrote:
 While checking the Phobos source I've found an interesting expression

 cast()(result[i]) = to!(E)(e);

 The 'cast()' means 'cast to mutable', e.g.

 class S {}
 void g(S x) {}
 void main() {
 const S s;
 g(cast()s);
 }

 But this is not documented in the D spec (CastParam cannot be empty).  
 Is
 this an "accept-invalid" bug, or just a feature not yet documented?


It gets even better: char[] x = "abc".dup; assert(is(typeof(cast(const)x) == const(char[])); I think you may have found a "bug" that should be a feature. It's like dmd is organically growing features that we might need ;) Is this software evolution? Scary! When will dmd decide that human life is a disease to be eradicated? When will the world be dominated by constinators?!!! I fear for my children. All kidding aside, I actually think the syntax makes sense. You are adding/removing modifiers, so just leave the type out of it. The only drawback is, you can't do a cast directly to a tail-const array, but that's not a huge deal, since const(T[]) implicitly casts to const(T)[]. I dub this feature "Type Modifier Casting". -Steve

cast(const), cast(immutable) etc are documented. cast() is not. See http://d-programming-language.org/expression.html#CastExpression

:O Of course, by documented, it shows the cast in the grammar (BTW, why the separate rule for cast(Type) when CastParam can be Type?), but not in the text. I almost never read the grammar unless I'm confused by the docs. This is almost as good as const_cast, although it seems too easy to screw up and remove const when you don't want to. -Steve
Jun 01 2011
prev sibling next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-01 13:42, Nick Sabalausky wrote:
 "Steven Schveighoffer" <schveiguy yahoo.com> wrote in message
 news:op.vwex37voeav7ka localhost.localdomain...
 
 On Wed, 01 Jun 2011 15:38:32 -0400, Andrej Mitrovic
 
 <andrej.mitrovich gmail.com> wrote:
 It seems to do even more than that:
 int a;
 const int b;
 immutable int c;
 shared int d;
 shared(const int) e;
 
 static assert(is(typeof(cast()a) == int));
 static assert(is(typeof(cast()b) == int));
 static assert(is(typeof(cast()c) == int));
 static assert(is(typeof(cast()d) == int));
 static assert(is(typeof(cast()e) == int));
 
 Talk about stealing the storm from std.traits.Unqual..
 
 On 6/1/11, KennyTM~ <kennytm gmail.com> wrote:
 While checking the Phobos source I've found an interesting expression
 
 cast()(result[i]) = to!(E)(e);
 
 The 'cast()' means 'cast to mutable', e.g.
 
 class S {}
 void g(S x) {}
 void main() {
 
 const S s;
 g(cast()s);
 
 }
 
 But this is not documented in the D spec (CastParam cannot be empty).
 Is this an "accept-invalid" bug, or just a feature not yet documented?


It gets even better: char[] x = "abc".dup; assert(is(typeof(cast(const)x) == const(char[])); I think you may have found a "bug" that should be a feature. It's like dmd is organically growing features that we might need ;) Is this software evolution? Scary! When will dmd decide that human life is a disease to be eradicated? When will the world be dominated by constinators?!!! I fear for my children. All kidding aside, I actually think the syntax makes sense. You are adding/removing modifiers, so just leave the type out of it. The only drawback is, you can't do a cast directly to a tail-const array, but that's not a huge deal, since const(T[]) implicitly casts to const(T)[]. I dub this feature "Type Modifier Casting".

It's nice in a way, but it's all based on the way cast handles modifiers. And I've always been a bit unconfortable with how that's handled (In fact, I was just thinking about this yesterday). Specifically, it seems extremely bad that it's so incredibly easy to accidentaly cast away things like const and immutable: For example, if I know I have an array of uint's, and I want to deal with the individual bytes, it's perfectly safe and sensible to cast it to a ubyte[] (a long as you factor in endianness, of course). So, you do "cast(ubyte[])myArray". But, OOPS!!: If myArray happened to be immutable, then merely trying to cast the type has inadvertantly cast-away immutable. Not good! Casting away const/immutable really, really should have to be explict. Of course, you can probably use some fancy helper templates to make sure you preserve all modifiers. But needing to do so is just asking for mistakes: it seems like a huge violation of "make the right way easy, and the wrong way hard".

You really shouldn't be casting much anyway. It's the sort of feature where you're only supposed to use it when you know what you're doing when you use it. And if there's really any possibility that you're dealing with immutable, perhaps you should be casting to const rather than mutable. Personally, I find how C++ created multiple types of cast (include const_cast) _highly_ annoying and generally useless, and I'm _very_ glad that D didn't do anything of the sort. - Jonathan M Davis
Jun 01 2011
parent "Nick Sabalausky" <a a.a> writes:
"Jonathan M Davis" <jmdavisProg gmx.com> wrote in message 
news:mailman.527.1306962732.14074.digitalmars-d puremagic.com...
 On 2011-06-01 13:42, Nick Sabalausky wrote:
 It's nice in a way, but it's all based on the way cast handles modifiers.
 And I've always been a bit unconfortable with how that's handled (In 
 fact,
 I was just thinking about this yesterday). Specifically, it seems
 extremely bad that it's so incredibly easy to accidentaly cast away 
 things
 like const and immutable:

 For example, if I know I have an array of uint's, and I want to deal with
 the individual bytes, it's perfectly safe and sensible to cast it to a
 ubyte[] (a long as you factor in endianness, of course). So, you do
 "cast(ubyte[])myArray". But, OOPS!!: If myArray happened to be immutable,
 then merely trying to cast the type has inadvertantly cast-away 
 immutable.
 Not good! Casting away const/immutable really, really should have to be
 explict.

 Of course, you can probably use some fancy helper templates to make sure
 you preserve all modifiers. But needing to do so is just asking for
 mistakes: it seems like a huge violation of "make the right way easy, and
 the wrong way hard".

You really shouldn't be casting much anyway. It's the sort of feature where you're only supposed to use it when you know what you're doing when you use it.

Well, when you're doing low-level stuff, type casting tends to be commonly needed. And also when dealing with OO class hierarchies. Problem is, like bearophile said, those uses are typically orthogonal to constness and immutability. It's nice that D's cast is multi-purpose, but I don't like that it's so easy to conflate the purposes of changing the modifiers and changing the base types since you're usually just trying to do one or the other. If we can change *just* the modifier with cast(immutable), cast(const) and cast(), without touching the base type, then that's fantastic. Certainly very useful. But it's equally useful (maybe even more useful due to the severe danger of casting to/from immutable), to similarly have a way to change just the base type without touching the modifier. Both of these "just one or the other" forms should be the typical usage of cast in 99+% of cases.
 And if there's really any possibility that you're dealing with immutable,
 perhaps you should be casting to const rather than mutable. Personally, I 
 find
 how C++ created multiple types of cast (include const_cast) _highly_ 
 annoying
 and generally useless, and I'm _very_ glad that D didn't do anything of 
 the
 sort.
 

Jun 01 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 01 Jun 2011 16:42:10 -0400, Nick Sabalausky <a a.a> wrote:

 "Steven Schveighoffer" <schveiguy yahoo.com> wrote in message
 It gets even better:

 char[] x = "abc".dup;

 assert(is(typeof(cast(const)x) == const(char[]));

 I think you may have found a "bug" that should be a feature.  It's like
 dmd is organically growing features that we might need ;)  Is this
 software evolution?  Scary!

 When will dmd decide that human life is a disease to be eradicated?   
 When
 will the world be dominated by constinators?!!!  I fear for my children.

 All kidding aside, I actually think the syntax makes sense.  You are
 adding/removing modifiers, so just leave the type out of it.  The only
 drawback is, you can't do a cast directly to a tail-const array, but
 that's not a huge deal, since const(T[]) implicitly casts to const(T)[].

 I dub this feature "Type Modifier Casting".

It's nice in a way, but it's all based on the way cast handles modifiers. And I've always been a bit unconfortable with how that's handled (In fact, I was just thinking about this yesterday). Specifically, it seems extremely bad that it's so incredibly easy to accidentaly cast away things like const and immutable:

Yes, it would be nice to have the equivalent of static_cast (which doesn't allow removing const in C++). I think however, we don't need compiler support for such things. We can probably do this via metaprogramming. However, having the ability to cast away or to const/immutable/shared/inout is very close to const_cast in C++. It fixes the problem where you just want to cast away const but inadvertently end up switching the type. We also need a static_cast for objects. Right now, casting to a derived object involves a dynamic lookup, but if you know that the dynamic lookup is not necessary, a cast which does not do a dynamic lookup can be much faster. For example, I could have a class A that contains a member of type X. Then you implement B : A and Y : X such that B's member X is always actually a Y. Re-storing the Y as another member is wasteful, and so is doing a dynamic cast for every usage of the member.
 Of course, you can probably use some fancy helper templates to make sure  
 you
 preserve all modifiers. But needing to do so is just asking for  
 mistakes: it
 seems like a huge violation of "make the right way easy, and the wrong  
 way
 hard".

I get what you are saying. I would be happy if default cast didn't allow casting away const or immutable, but I think we would have a difficult time introducing such a change. Note however, C++ has good success with static_cast vs the old C-style cast (which is supported), so there is hope. The more troubling thing is when you *want* to do a dynamic cast (which can only be done via the cast(X) style), you can inadvertently remove const or immutable. -Steve
Jun 01 2011
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Stroustrup: What happen ?
Meyers: Somebody set up us the bomb.
Spolsky: We get signal.
Stroustrup: What !
Spolsky: Main screen turn on.
Stroustrup: It=92s you !!
Bright: How are you gentlemen !!
Bright: All your base are belong to us.
Bright: You are on the way to destruction.
Stroustrup: What you say !!
Bright: You have no chance to survive make your time.
Bright: Ha ha ha ha =85
Jun 01 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message 
news:mailman.529.1306975584.14074.digitalmars-d puremagic.com...
Stroustrup: What happen ?
Meyers: Somebody set up us the bomb.
Spolsky: We get signal.
Stroustrup: What !
Spolsky: Main screen turn on.
Stroustrup: Itís you !!
Bright: How are you gentlemen !!
Bright: All your base are belong to us.
Bright: You are on the way to destruction.
Stroustrup: What you say !!
Bright: You have no chance to survive make your time.
Bright: Ha ha ha ha Ö

I don't care how old it is in "internet meme" time: I'll never get tired of those classic lines :) ('course it's much older than even that...)
Jun 01 2011
parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
On 02/06/2011 06:08, Nick Sabalausky wrote:
 "Andrej Mitrovic"<andrej.mitrovich gmail.com>  wrote in message
 news:mailman.529.1306975584.14074.digitalmars-d puremagic.com...
 Stroustrup: What happen ?
 Meyers: Somebody set up us the bomb.
 Spolsky: We get signal.
 Stroustrup: What !
 Spolsky: Main screen turn on.
 Stroustrup: Itís you !!
 Bright: How are you gentlemen !!
 Bright: All your base are belong to us.
 Bright: You are on the way to destruction.
 Stroustrup: What you say !!
 Bright: You have no chance to survive make your time.
 Bright: Ha ha ha ha Ö

I don't care how old it is in "internet meme" time: I'll never get tired of those classic lines :) ('course it's much older than even that...)

O RLY? :P -- Bruno Medeiros - Software Engineer
Jun 02 2011
parent "Nick Sabalausky" <a a.a> writes:
"Bruno Medeiros" <brunodomedeiros+spam com.gmail> wrote in message 
news:is8a25$gka$1 digitalmars.com...
 On 02/06/2011 06:08, Nick Sabalausky wrote:
 "Andrej Mitrovic"<andrej.mitrovich gmail.com>  wrote in message
 news:mailman.529.1306975584.14074.digitalmars-d puremagic.com...
 Stroustrup: What happen ?
 Meyers: Somebody set up us the bomb.
 Spolsky: We get signal.
 Stroustrup: What !
 Spolsky: Main screen turn on.
 Stroustrup: Itís you !!
 Bright: How are you gentlemen !!
 Bright: All your base are belong to us.
 Bright: You are on the way to destruction.
 Stroustrup: What you say !!
 Bright: You have no chance to survive make your time.
 Bright: Ha ha ha ha Ö

I don't care how old it is in "internet meme" time: I'll never get tired of those classic lines :) ('course it's much older than even that...)

O RLY? :P

CAN I HAZ FUN OLD MEMEZ PLZ, K THNX BYE! :)
Jun 02 2011
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/1/2011 12:22 PM, KennyTM~ wrote:
 But this is not documented in the D spec (CastParam cannot be empty). Is this
an
 "accept-invalid" bug, or just a feature not yet documented?

A feature that coincidentally just got documented :-)
Jun 01 2011
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 02 Jun 2011 01:32:52 -0400, Walter Bright  
<newshound2 digitalmars.com> wrote:

 On 6/1/2011 12:22 PM, KennyTM~ wrote:
 But this is not documented in the D spec (CastParam cannot be empty).  
 Is this an
 "accept-invalid" bug, or just a feature not yet documented?

A feature that coincidentally just got documented :-)

Seems incorrect: Casting to a CastQual adds the qualifier to the type of the UnaryExpression. Casting to the empty ( ) has the effect of removing any top level const or immutable type modifiers from the type of the UnaryExpression. From these descriptions, I would expect the following asserts to pass: const int a; auto b = cast(shared)a; // add shared to the type assert(is(typeof(b) == shared const int)); shared const int x; auto y = cast()x; // remove const or immutable from the type assert(is(typeof(y) == shared int)); But both fail. Seems like both expressions set the modifiers to their args. -Steve
Jun 02 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
We put a compiler in yo compiler so you can CTFE while you CTFE.
Jun 02 2011
prev sibling next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-02 09:02, Bruno Medeiros wrote:
 On 01/06/2011 22:12, Jonathan M Davis wrote:
 It's nice in a way, but it's all based on the way cast handles
 modifiers.
 
 And I've always been a bit unconfortable with how that's handled (In
 fact, I was just thinking about this yesterday). Specifically, it
 seems extremely bad that it's so incredibly easy to accidentaly cast
 away things like const and immutable:
 
 For example, if I know I have an array of uint's, and I want to deal
 with the individual bytes, it's perfectly safe and sensible to cast
 it to a ubyte[] (a long as you factor in endianness, of course). So,
 you do "cast(ubyte[])myArray". But, OOPS!!: If myArray happened to
 be immutable, then merely trying to cast the type has inadvertantly
 cast-away immutable. Not good! Casting away const/immutable really,
 really should have to be explict.
 
 Of course, you can probably use some fancy helper templates to make
 sure you preserve all modifiers. But needing to do so is just asking
 for mistakes: it seems like a huge violation of "make the right way
 easy, and the wrong way hard".


You really shouldn't be casting much anyway. It's the sort of feature where you're only supposed to use it when you know what you're doing when you use it. And if there's really any possibility that you're dealing with immutable, perhaps you should be casting to const rather than mutable. Personally, I find how C++ created multiple types of cast (include const_cast)_highly_ annoying and generally useless, and I'm_very_ glad that D didn't do anything of the sort. - Jonathan M Davis

"you're only supposed to use it when you know what you're doing when you use it" Well, that's kinda the requirement for any feature, isn't it?... :P Well, kinda, I do know what you mean. Yes, one needs to properly learn how cast() works, but that doesn't mean it would not be better for the feature to be designed in a way that is easier to learn (and just as powerful to use), or actually, it doesn't mean that even if you do know how cast() works, that you are not still likely to make a mistake when using it.

Really, you should only be using casts when you need a cast, and you should be careful when you use them. So, you have to know what you're doing and why in that particular instance and not use them willy-nilly. In most code, casts should be quite rare. If you're doing a lot of low-level stuff, then they might be more common, but in general, they're a sledgehammer that shouldn't be used except when you really need them.
 So pretty much I agree with Nick here. I think me and a few others have
 mentioned it in the past, that the way cast works makes it somewhat easy
 to trip over one's foot and cast away something that was not intended.
 This may be a bit more common now and in the future as people use more
 and more of the newer D modifiers (shared, immutable, etc.).

I really don't know what you'd do other than introducing stuff like C++'s const_cast, and I know very few programmers who actually use any of those special casts. In most cases, they just use C-style casts. It just gets too complicated to determine what the correct cast to use in a particular situation is. And C++ is the only language I know of with more than one type of cast. I think that it's _far_ better to have the compiler figure that out for you. Some templates could be created for changing one aspect of type (such as mutability or shared-ness) if people really want that, but since casts should generally be rare in the first place, the effort of getting them right shouldn't be very high anyway. Regardless, I'd _hate_ to see the built-in cast operator altered to be more complicated. I _much_ prefer it to C++'s special casts, and I'm _very_ glad that they were not one of the C++ features to be carried over to D. - Jonathan M Davis
Jun 02 2011
parent bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 Personally, I find the added complexity of C++'s special casts to _far_ 
 outweight what benefit they give you.

I don't want to copy C++, I prefer casts better designed than C++ ones, and probably they don't need language-level support. I'd like a cast to cast enums safely, to be integrated into to!(). A StaticObjCast just for statically and safely cast object references. One cast to change the const status of a type const <-> immutable <-> mutable. I'd like to keep unqual and to!(). dynCast is better explicit, because it has a not small runtime cost, and its purpose is quite different from other casts, so such differences are worth showing visually too. Bye, bearophile
Jun 03 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 02 Jun 2011 17:52:41 -0400, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On 2011-06-02 09:02, Bruno Medeiros wrote:
 On 01/06/2011 22:12, Jonathan M Davis wrote:
 It's nice in a way, but it's all based on the way cast handles
 modifiers.

 And I've always been a bit unconfortable with how that's handled  



 fact, I was just thinking about this yesterday). Specifically, it
 seems extremely bad that it's so incredibly easy to accidentaly  



 away things like const and immutable:

 For example, if I know I have an array of uint's, and I want to  



 with the individual bytes, it's perfectly safe and sensible to cast
 it to a ubyte[] (a long as you factor in endianness, of course).  



 you do "cast(ubyte[])myArray". But, OOPS!!: If myArray happened to
 be immutable, then merely trying to cast the type has inadvertantly
 cast-away immutable. Not good! Casting away const/immutable really,
 really should have to be explict.

 Of course, you can probably use some fancy helper templates to make
 sure you preserve all modifiers. But needing to do so is just  



 for mistakes: it seems like a huge violation of "make the right way
 easy, and the wrong way hard".


You really shouldn't be casting much anyway. It's the sort of feature where you're only supposed to use it when you know what you're doing when you use it. And if there's really any possibility that you're dealing with immutable, perhaps you should be casting to const rather than mutable. Personally, I find how C++ created multiple types of

 (include const_cast)_highly_ annoying and generally useless, and
 I'm_very_ glad that D didn't do anything of the sort.

 - Jonathan M Davis

"you're only supposed to use it when you know what you're doing when you use it" Well, that's kinda the requirement for any feature, isn't it?... :P Well, kinda, I do know what you mean. Yes, one needs to properly learn how cast() works, but that doesn't mean it would not be better for the feature to be designed in a way that is easier to learn (and just as powerful to use), or actually, it doesn't mean that even if you do know how cast() works, that you are not still likely to make a mistake when using it.

Really, you should only be using casts when you need a cast, and you should be careful when you use them. So, you have to know what you're doing and why in that particular instance and not use them willy-nilly. In most code, casts should be quite rare. If you're doing a lot of low-level stuff, then they might be more common, but in general, they're a sledgehammer that shouldn't be used except when you really need them.

Casting is the recommended way to determine if something is actually a derived type: interface I {} class C : I {} void foo(I i) // change this to const(I) and you have a huge const bug! { if(C c = cast(C)i) { // optimized branch } else { // default branch } } so it's not so easy to say you should "never" cast. BTW, dcollections uses this quite a bit to support operations between multiple types of collections. It would be nice if at least dynamic cast (with the added rules to prevent casting away const/immutable/shared) was a different syntax from cast, since it's a completely safe usage of casting (as long as you manually forward modifiers). It's as safe as to! is when used with the right context. -Steve
Jun 02 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-02 15:13, Steven Schveighoffer wrote:
 On Thu, 02 Jun 2011 17:52:41 -0400, Jonathan M Davis <jmdavisProg gmx.com>
 
 wrote:
 On 2011-06-02 09:02, Bruno Medeiros wrote:
 On 01/06/2011 22:12, Jonathan M Davis wrote:
 It's nice in a way, but it's all based on the way cast handles
 modifiers.
 
 And I've always been a bit unconfortable with how that's handled



(In
 fact, I was just thinking about this yesterday). Specifically, it
 seems extremely bad that it's so incredibly easy to accidentaly



cast
 away things like const and immutable:
 
 For example, if I know I have an array of uint's, and I want to



deal
 with the individual bytes, it's perfectly safe and sensible to cast
 it to a ubyte[] (a long as you factor in endianness, of course).



So,
 you do "cast(ubyte[])myArray". But, OOPS!!: If myArray happened to
 be immutable, then merely trying to cast the type has inadvertantly
 cast-away immutable. Not good! Casting away const/immutable really,
 really should have to be explict.
 
 Of course, you can probably use some fancy helper templates to make
 sure you preserve all modifiers. But needing to do so is just



asking
 for mistakes: it seems like a huge violation of "make the right way
 easy, and the wrong way hard".


You really shouldn't be casting much anyway. It's the sort of feature where you're only supposed to use it when you know what you're doing when you use it. And if there's really any possibility that you're dealing with immutable, perhaps you should be casting to const rather than mutable. Personally, I find how C++ created multiple types of

cast
 (include const_cast)_highly_ annoying and generally useless, and
 I'm_very_ glad that D didn't do anything of the sort.
 
 - Jonathan M Davis

"you're only supposed to use it when you know what you're doing when you use it" Well, that's kinda the requirement for any feature, isn't it?... :P Well, kinda, I do know what you mean. Yes, one needs to properly learn how cast() works, but that doesn't mean it would not be better for the feature to be designed in a way that is easier to learn (and just as powerful to use), or actually, it doesn't mean that even if you do know how cast() works, that you are not still likely to make a mistake when using it.

Really, you should only be using casts when you need a cast, and you should be careful when you use them. So, you have to know what you're doing and why in that particular instance and not use them willy-nilly. In most code, casts should be quite rare. If you're doing a lot of low-level stuff, then they might be more common, but in general, they're a sledgehammer that shouldn't be used except when you really need them.

Casting is the recommended way to determine if something is actually a derived type: interface I {} class C : I {} void foo(I i) // change this to const(I) and you have a huge const bug! { if(C c = cast(C)i) { // optimized branch } else { // default branch } } so it's not so easy to say you should "never" cast. BTW, dcollections uses this quite a bit to support operations between multiple types of collections. It would be nice if at least dynamic cast (with the added rules to prevent casting away const/immutable/shared) was a different syntax from cast, since it's a completely safe usage of casting (as long as you manually forward modifiers). It's as safe as to! is when used with the right context.

No. It's not the case that you should _never_ cast, but in most programs, it should still be rare. And yes, casting is the proper way to determine whether an object's type, is derived from a particular class, but it's generally considered bad OO programming to have to ask that sort of question very often. There are a few places that you're forced to (such as opEquals), but in general, it's a symptom of a bad design. Code should generally be written in such a manner that you either know what it's type is or don't care. You shouldn't generally have to ask it. Obviously, there are exceptions, but they should be exceptions rather than the norm. As such, casts should be fairly rare. Personally, I find the added complexity of C++'s special casts to _far_ outweight what benefit they give you. Yes, having something like Java's instanceof instead of having to cast to check whether an object's type is derived from a particular type would arguably be an improvement, but even it shouldn't be used all that often, and I definitely don't think that creating a set of cast operators for different types of cast would be a good idea at all. - Jonathan M Davis
Jun 02 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 02 Jun 2011 18:39:48 -0400, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On 2011-06-02 15:13, Steven Schveighoffer wrote:
 On Thu, 02 Jun 2011 17:52:41 -0400, Jonathan M Davis  
 <jmdavisProg gmx.com>

 wrote:
 On 2011-06-02 09:02, Bruno Medeiros wrote:
 On 01/06/2011 22:12, Jonathan M Davis wrote:
 It's nice in a way, but it's all based on the way cast handles
 modifiers.

 And I've always been a bit unconfortable with how that's handled



(In
 fact, I was just thinking about this yesterday). Specifically,  





 seems extremely bad that it's so incredibly easy to accidentaly



cast
 away things like const and immutable:

 For example, if I know I have an array of uint's, and I want to



deal
 with the individual bytes, it's perfectly safe and sensible to  





 it to a ubyte[] (a long as you factor in endianness, of course).



So,
 you do "cast(ubyte[])myArray". But, OOPS!!: If myArray happened  





 be immutable, then merely trying to cast the type has  





 cast-away immutable. Not good! Casting away const/immutable  





 really should have to be explict.

 Of course, you can probably use some fancy helper templates to  





 sure you preserve all modifiers. But needing to do so is just



asking
 for mistakes: it seems like a huge violation of "make the right  





 easy, and the wrong way hard".


You really shouldn't be casting much anyway. It's the sort of



 where you're only supposed to use it when you know what you're  



 when you use it. And if there's really any possibility that you're
 dealing with immutable, perhaps you should be casting to const  



 than mutable. Personally, I find how C++ created multiple types of

cast
 (include const_cast)_highly_ annoying and generally useless, and
 I'm_very_ glad that D didn't do anything of the sort.

 - Jonathan M Davis

"you're only supposed to use it when you know what you're doing when


 use it"
 Well, that's kinda the requirement for any feature, isn't it?... :P
 Well, kinda, I do know what you mean. Yes, one needs to properly  


 how cast() works, but that doesn't mean it would not be better for  


 feature to be designed in a way that is easier to learn (and just as
 powerful to use), or actually, it doesn't mean that even if you do  


 how cast() works, that you are not still likely to make a mistake  


 using it.

Really, you should only be using casts when you need a cast, and you should be careful when you use them. So, you have to know what you're doing and why in that particular instance and not use them willy-nilly. In most code, casts should be quite rare. If you're doing a lot of low-level stuff, then

 might be more common, but in general, they're a sledgehammer that
 shouldn't be
 used except when you really need them.

Casting is the recommended way to determine if something is actually a derived type: interface I {} class C : I {} void foo(I i) // change this to const(I) and you have a huge const bug! { if(C c = cast(C)i) { // optimized branch } else { // default branch } } so it's not so easy to say you should "never" cast. BTW, dcollections uses this quite a bit to support operations between multiple types of collections. It would be nice if at least dynamic cast (with the added rules to prevent casting away const/immutable/shared) was a different syntax from cast, since it's a completely safe usage of casting (as long as you manually forward modifiers). It's as safe as to! is when used with the right context.

No. It's not the case that you should _never_ cast, but in most programs, it should still be rare. And yes, casting is the proper way to determine whether an object's type, is derived from a particular class, but it's generally considered bad OO programming to have to ask that sort of question very often.

 There are a few places that you're forced to (such as opEquals), but in
 general, it's a symptom of a bad design. Code should generally be  
 written in
 such a manner that you either know what it's type is or don't care. You
 shouldn't generally have to ask it. Obviously, there are exceptions, but  
 they
 should be exceptions rather than the norm. As such, casts should be  
 fairly
 rare.

Any place you have double-dispatch, you need to use it in the dispatch function.
 Personally, I find the added complexity of C++'s special casts to _far_
 outweight what benefit they give you. Yes, having something like Java's
 instanceof instead of having to cast to check whether an object's type is
 derived from a particular type would arguably be an improvement, but  
 even it
 shouldn't be used all that often, and I definitely don't think that  
 creating a
 set of cast operators for different types of cast would be a good idea  
 at all.

added complexity? How so? There are four types of casts: static_cast -> cast without discarding const or volatile const_cast -> cast only removing const or volatile dynamic_cast -> do a runtime cast to see if an object is actually a derived type reinterpret_cast -> force everything, and avoid any cast overloads. In all of these, only const_cast and reinterpret_cast are unsafe. Each one clearly separates what you wish to do. this is not complication, this is expressiveness. Something that D's casting does not have. D's casting conflates multiple things together, and because of the "I trust you" nature that casts have, you can easily make mistakes without complaint from the compiler. The fact that a dynamic cast is inherently unsafe in D is unnecessary. I don't know if it will change, but I can't say it's better than C++. It can be made better than C++, but I think I'd rather have the four cast types than what D has now. -Steve
Jun 02 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-02 16:22, Steven Schveighoffer wrote:
 On Thu, 02 Jun 2011 18:39:48 -0400, Jonathan M Davis <jmdavisProg gmx.com>
 
 wrote:
 On 2011-06-02 15:13, Steven Schveighoffer wrote:
 On Thu, 02 Jun 2011 17:52:41 -0400, Jonathan M Davis
 <jmdavisProg gmx.com>
 
 wrote:
 On 2011-06-02 09:02, Bruno Medeiros wrote:
 On 01/06/2011 22:12, Jonathan M Davis wrote:
 It's nice in a way, but it's all based on the way cast handles
 modifiers.
 
 And I've always been a bit unconfortable with how that's handled



(In
 fact, I was just thinking about this yesterday). Specifically,





it
 seems extremely bad that it's so incredibly easy to accidentaly



cast
 away things like const and immutable:
 
 For example, if I know I have an array of uint's, and I want to



deal
 with the individual bytes, it's perfectly safe and sensible to





cast
 it to a ubyte[] (a long as you factor in endianness, of course).



So,
 you do "cast(ubyte[])myArray". But, OOPS!!: If myArray happened





to
 be immutable, then merely trying to cast the type has





inadvertantly
 cast-away immutable. Not good! Casting away const/immutable





really,
 really should have to be explict.
 
 Of course, you can probably use some fancy helper templates to





make
 sure you preserve all modifiers. But needing to do so is just



asking
 for mistakes: it seems like a huge violation of "make the right





way
 easy, and the wrong way hard".


You really shouldn't be casting much anyway. It's the sort of



feature
 where you're only supposed to use it when you know what you're



doing
 when you use it. And if there's really any possibility that you're
 dealing with immutable, perhaps you should be casting to const



rather
 than mutable. Personally, I find how C++ created multiple types of

cast
 (include const_cast)_highly_ annoying and generally useless, and
 I'm_very_ glad that D didn't do anything of the sort.
 
 - Jonathan M Davis

"you're only supposed to use it when you know what you're doing when


you
 use it"
 Well, that's kinda the requirement for any feature, isn't it?... :P
 Well, kinda, I do know what you mean. Yes, one needs to properly


learn
 how cast() works, but that doesn't mean it would not be better for


the
 feature to be designed in a way that is easier to learn (and just as
 powerful to use), or actually, it doesn't mean that even if you do


know
 how cast() works, that you are not still likely to make a mistake


when
 using it.

Really, you should only be using casts when you need a cast, and you should be careful when you use them. So, you have to know what you're doing and why in that particular instance and not use them willy-nilly. In most code, casts should be quite rare. If you're doing a lot of low-level stuff, then

they
 might be more common, but in general, they're a sledgehammer that
 shouldn't be
 used except when you really need them.

Casting is the recommended way to determine if something is actually a derived type: interface I {} class C : I {} void foo(I i) // change this to const(I) and you have a huge const bug! { if(C c = cast(C)i) { // optimized branch } else { // default branch } } so it's not so easy to say you should "never" cast. BTW, dcollections uses this quite a bit to support operations between multiple types of collections. It would be nice if at least dynamic cast (with the added rules to prevent casting away const/immutable/shared) was a different syntax from cast, since it's a completely safe usage of casting (as long as you manually forward modifiers). It's as safe as to! is when used with the right context.

No. It's not the case that you should _never_ cast, but in most programs, it should still be rare. And yes, casting is the proper way to determine whether an object's type, is derived from a particular class, but it's generally considered bad OO programming to have to ask that sort of question very often. There are a few places that you're forced to (such as opEquals), but in general, it's a symptom of a bad design. Code should generally be written in such a manner that you either know what it's type is or don't care. You shouldn't generally have to ask it. Obviously, there are exceptions, but they should be exceptions rather than the norm. As such, casts should be fairly rare.

Any place you have double-dispatch, you need to use it in the dispatch function.
 Personally, I find the added complexity of C++'s special casts to _far_
 outweight what benefit they give you. Yes, having something like Java's
 instanceof instead of having to cast to check whether an object's type is
 derived from a particular type would arguably be an improvement, but
 even it
 shouldn't be used all that often, and I definitely don't think that
 creating a
 set of cast operators for different types of cast would be a good idea
 at all.

added complexity? How so? There are four types of casts: static_cast -> cast without discarding const or volatile const_cast -> cast only removing const or volatile dynamic_cast -> do a runtime cast to see if an object is actually a derived type reinterpret_cast -> force everything, and avoid any cast overloads. In all of these, only const_cast and reinterpret_cast are unsafe. Each one clearly separates what you wish to do. this is not complication, this is expressiveness. Something that D's casting does not have. D's casting conflates multiple things together, and because of the "I trust you" nature that casts have, you can easily make mistakes without complaint from the compiler. The fact that a dynamic cast is inherently unsafe in D is unnecessary. I don't know if it will change, but I can't say it's better than C++. It can be made better than C++, but I think I'd rather have the four cast types than what D has now.

It is definitely added complexity. Now, it allows you to be more explicit and what you want and so it does add expressiveness as well, but with one cast, you know which cast you need to use. With 4, you have to figure out which one to use in a particular instance. Honestly, in discussing the C++ special casts with other programmers in the past, I've gotten the impression that your average C++ programmer does not understand them all, and many of them just use C-style casts all the time. I care about such details in a language and try and understand them, and I confess that I still am not really sure of the exact difference between static_cast and reinterpret_cast and when you're supposed to use one or the other - especially when casting pointers. const_cast and dynamic_cast are easy enough, but having 4 casts instead of 1 where the compiler just does the right thing is definitely added complexity, and it's highly subjective as to whether the added expressivness is worth the complexity. I don't think that it is. You obviously disagree. And for better or worse, D took the route of simplicity rather than expressiveness in this case. - Jonathan M Davis
Jun 02 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 02 Jun 2011 19:41:18 -0400, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On 2011-06-02 16:22, Steven Schveighoffer wrote:

 this is not complication, this is expressiveness. Something that D's
 casting does not have. D's casting conflates multiple things together,
 and because of the "I trust you" nature that casts have, you can easily
 make mistakes without complaint from the compiler. The fact that a
 dynamic cast is inherently unsafe in D is unnecessary. I don't know if  
 it
 will change, but I can't say it's better than C++. It can be made better
 than C++, but I think I'd rather have the four cast types than what D  
 has
 now.

It is definitely added complexity. Now, it allows you to be more explicit and what you want and so it does add expressiveness as well, but with one cast, you know which cast you need to use.

Think about ref. Ref has two purposes, passing a value by reference because you are going to use it as a return value, and passing a value by reference because it's cheaper to pass by reference. But the compiler cannot tell what you mean, so things like rvalues cannot be passed by reference, even if it's for the latter case (because it's cheaper). In C++, they "fixed" this by allowing const references to bind to rvalues, but the problem there is, you don't know if the person wanted to allow rvalues through. There is no way to specify "I only want cheaply passed lvalues here!" What results is, it's difficult to determine the *intentions* of the user given the code he wrote, both for the compiler and the reviewer. This leads to possible reliance on documentation, and no enforcement. This is what I'd call false simplicity. Yes, you didn't need to add another keyword, but is it really simpler? What happens is, it's simpler to make bugs, and impossible to express what you mean in some cases. So is giving more expressive meaning to casts adding complexity? I look at it this way: it results in more thinking on the front end (which cast should I use?) vs. 10x more thinking on the back end (what the hell did the author mean by this cast? Is it really supposed to strip out const?). Note also, the front end rules are defined by the C++ standard, whereas the reasoning for using a generic all-in-one cast is only locked inside the author's head. Hopefully he's documented that for you.
 With 4, you have to figure out which one
 to use in a particular instance. Honestly, in discussing the C++ special  
 casts
 with other programmers in the past, I've gotten the impression that your
 average C++ programmer does not understand them all, and many of them  
 just use
 C-style casts all the time.

Such easy-outs are part of the problem -- if you make the more dangerous path easier than the more expressive and safer path, people give up trying to learn the system. They might even think they are using clever shortcuts. Without such an easy out, you will learn the other casts eventually. I've been a part of teams where C-style casts are not an option, and you just figure it out.
 I care about such details in a language and try
 and understand them, and I confess that I still am not really sure of the
 exact difference between static_cast and reinterpret_cast and when you're
 supposed to use one or the other - especially when casting pointers.

I admit too, I was not correct in remembering how reinterpret_cast works exactly (my C++ skills are suffering from bit-rot) -- it does not allow casting away of const. However, the rest of my description is accurate. It basically treats the data as if it was the given type without any implicit or explicit conversions. For example, if you static_cast an int to a float, it create a float out of an int (i.e 5 turns into 5.0). However, if you reinterpret_cast an int to a float, it will not change the bit pattern at all, what you get is what a float would be with that bit pattern. BTW, as far as I can tell, static or reinterpret casting pointers is identical, you should prefer static_cast however because it's safer. The hilarious thing about reinterpret_cast is, using the casted data is undefined. All you are allowed to do with it is cast back to the original data. This may seem useless but gets around some static typing limitations (for example, if you have functions that accept void * data, and you have to override that function, you reinterpret_cast the data to void *, then reinterpret_cast it back on the other end). I feel D does not need an equivalent reinterpret_cast. You can achieve the same thing via pointer casting (e.g. *(cast(T*)&u) ). Note this is entirely possible in D because of the inability to override the & operator. D already has a clearly delineated const_cast (the subject of this thread). The problem is, all other cast types are munged together, with const_cast thrown in for good measure. I think if we stopped debating the value of C++ casts, and simply tried to find a decent syntax for separating out dynamic_cast, we could have all these options without the verbosity. I'd even go as far to say that dynamic_cast can be a library function -- it's not really a cast. It can even be made a part of std.conv.to. -Steve P.S. I used the information from this SO article to help me write this: http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-and-reinterpret-cast-be-used
Jun 02 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-03 05:14, bearophile wrote:
 Jonathan M Davis:
 Personally, I find the added complexity of C++'s special casts to _far_
 outweight what benefit they give you.

I don't want to copy C++, I prefer casts better designed than C++ ones, and probably they don't need language-level support. I'd like a cast to cast enums safely, to be integrated into to!(). A StaticObjCast just for statically and safely cast object references. One cast to change the const status of a type const <-> immutable <-> mutable. I'd like to keep unqual and to!(). dynCast is better explicit, because it has a not small runtime cost, and its purpose is quite different from other casts, so such differences are worth showing visually too.

And I would argue that the fact that you have separate casts in the first place is 90% of the problem. Sure, you could design the casts better, but having to deal with more than one type of cast is the core of my complaint in the first place. I find it to be very annoying and of little value. - Jonathan M Davis
Jun 03 2011
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-03 16:33, Stewart Gordon wrote:
 On 01/06/2011 21:51, Steven Schveighoffer wrote:
 On Wed, 01 Jun 2011 16:38:42 -0400, KennyTM~ <kennytm gmail.com> wrote:

 cast(const), cast(immutable) etc are documented. cast() is not. See
 http://d-programming-language.org/expression.html#CastExpression


What is that site? A reference for how the compiler actually behaves, as opposed to the spec?

d-programming-language.org is the site that is going to become the main site for D. It's not quite far enough along to replace the portions of www.digitalmars.com on D, but once it is, a lot of the stuff which is currently on www.digitalmars.com will redirect to d-programming-language.org. - Jonathan M Davis
Jun 03 2011