www.digitalmars.com         C & C++   DMDScript  

D - Cast operators

reply "Matthew Wilson" <dmd synesis.com.au> writes:
Any chance of our getting away from the overused round braces in casts, and
adopt something less ambiguous, along the lines of the C++ casts?

It seems like a retrograde step.
Sep 17 2003
next sibling parent reply "Philippe Mori" <philippe_mori hotmail.com> writes:
 Any chance of our getting away from the overused round braces in casts,

 adopt something less ambiguous, along the lines of the C++ casts?

 It seems like a retrograde step.

Me I prefer function style cast... but I think that it should be the same as for template so that anyone could write it prefered cast as it is possible in C++. I would also like to have more cast as in C++ where we can explictly tell the compiler which kind of casting we want to allows. In fact, I would even like to have more cast than in C++. Some of the cast that I think of: static_cast // as in C++ reinterpret_cast // low level bit reinterpret const_cast // as in C++ (we should add const support to D) dynamic_cast // base to derived implicit_cast // Allows if cast/conversion is implictly allowed without error (and disable any vendor specific warnings) range_cast // Ensure that the value fit in the target same_layout_cast // allowed if the layout is the same (x, y, z vs pt[3] or renamed member) enum_cast // Similar to range cast but only for enums fit_cast // fit to target range (any value lower than target min would be set to target min or -INF for floatting points,...) ... and some more for plateform dependant cast, similar type cast (int to uint) .... We should have one cast for each kind of casting that can be done... and have cast if allowed on the current plateform vs defined exactly by the language... And I'd like to be able to add my owns...
Sep 17 2003
parent reply "Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> writes:
"Philippe Mori" <philippe_mori hotmail.com> escreveu na mensagem
news:bk9q8l$27ov$1 digitaldaemon.com...
 Any chance of our getting away from the overused round braces in casts,

 adopt something less ambiguous, along the lines of the C++ casts?

 It seems like a retrograde step.

Me I prefer function style cast... but I think that it should be the same

 for
 template so that anyone could write it prefered cast as it is possible in
 C++.

 I would also like to have more cast as in C++ where we can explictly tell
 the compiler which kind of casting we want to allows. In fact, I would

 like to have more cast than in C++. Some of the cast that I think of:

 static_cast            // as in C++
 reinterpret_cast    // low level bit reinterpret
 const_cast            // as in C++ (we should add const support to D)
 dynamic_cast        // base to derived

 implicit_cast        // Allows if cast/conversion is implictly allowed
     without error (and disable any vendor specific warnings)

 range_cast            // Ensure that the value fit in the target

 same_layout_cast    // allowed if the layout is the same (x, y, z vs pt[3]
     or renamed member)

 enum_cast        // Similar to range cast but only for enums

 fit_cast            // fit to target range (any value lower than target
     min would be set to target min or -INF for floatting points,...)

 ...

 and some more for plateform dependant cast, similar type cast (int to

 ....

 We should have one cast for each kind of casting that can be done...
 and have cast if allowed on the current plateform vs defined exactly
 by the language...

 And I'd like to be able to add my owns...

IMO we should just keep the simple cast (using a "cast(type, value)" syntax to reduce the parameters) and have all the other casts as templates. If we do it this way we can keep the language clean of one hundred and one new keywords and the syntax of templates will certainly improve (just imagine dozens of developers frustrated with explicit instantiantion ;). Also templates are the standard way to provide generic code (i.e. you would be able to add your owns). --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.518 / Virus Database: 316 - Release Date: 11/9/2003
Sep 17 2003
next sibling parent reply "Charles Sanders" <sanders-consulting comcast.net> writes:
This gets my vote.  Keep the (cast) I vote.

One thing that does worry me, is that there are now a ton of keywords in D,
I realize that there all needed, but what are everyone elses thoughts on
this ?  Id like to keep it to as little as possible.

Charles
"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message
news:bkaqnn$lbt$1 digitaldaemon.com...
 "Philippe Mori" <philippe_mori hotmail.com> escreveu na mensagem
 news:bk9q8l$27ov$1 digitaldaemon.com...
 Any chance of our getting away from the overused round braces in



 and
 adopt something less ambiguous, along the lines of the C++ casts?

 It seems like a retrograde step.

Me I prefer function style cast... but I think that it should be the


 as
 for
 template so that anyone could write it prefered cast as it is possible


 C++.

 I would also like to have more cast as in C++ where we can explictly


 the compiler which kind of casting we want to allows. In fact, I would

 like to have more cast than in C++. Some of the cast that I think of:

 static_cast            // as in C++
 reinterpret_cast    // low level bit reinterpret
 const_cast            // as in C++ (we should add const support to D)
 dynamic_cast        // base to derived

 implicit_cast        // Allows if cast/conversion is implictly allowed
     without error (and disable any vendor specific warnings)

 range_cast            // Ensure that the value fit in the target

 same_layout_cast    // allowed if the layout is the same (x, y, z vs


     or renamed member)

 enum_cast        // Similar to range cast but only for enums

 fit_cast            // fit to target range (any value lower than target
     min would be set to target min or -INF for floatting points,...)

 ...

 and some more for plateform dependant cast, similar type cast (int to

 ....

 We should have one cast for each kind of casting that can be done...
 and have cast if allowed on the current plateform vs defined exactly
 by the language...

 And I'd like to be able to add my owns...

IMO we should just keep the simple cast (using a "cast(type, value)"

 to reduce the parameters) and have all the other casts as templates. If we
 do it this way we can keep the language clean of one hundred and one new
 keywords and the syntax of templates will certainly improve (just imagine
 dozens of developers frustrated with explicit instantiantion ;). Also
 templates are the standard way to provide generic code (i.e. you would be
 able to add your owns).



 ---
 Outgoing mail is certified Virus Free.
 Checked by AVG anti-virus system (http://www.grisoft.com).
 Version: 6.0.518 / Virus Database: 316 - Release Date: 11/9/2003

Sep 17 2003
parent reply Felix <Felix_member pathlink.com> writes:
What about smthng like "variable.doCast(newType)" (standard method call). Yes,
will be more difficult for expressions, but not always:

(variable1+variable2/variable4).doCast(newType)

Me, one, I would preffer this to (newType) (Variable1+Variable2);
It is really necessar to have an operator-based syntax?


Also, other casts should be easier to add.

Yes, and please drop the "_" in function names. Just an innocent idea.



In article <bkav5t$rdo$1 digitaldaemon.com>, Charles Sanders says...
This gets my vote.  Keep the (cast) I vote.

One thing that does worry me, is that there are now a ton of keywords in D,
I realize that there all needed, but what are everyone elses thoughts on
this ?  Id like to keep it to as little as possible.

Charles
"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message
news:bkaqnn$lbt$1 digitaldaemon.com...
 "Philippe Mori" <philippe_mori hotmail.com> escreveu na mensagem
 news:bk9q8l$27ov$1 digitaldaemon.com...
 Any chance of our getting away from the overused round braces in



 and
 adopt something less ambiguous, along the lines of the C++ casts?

 It seems like a retrograde step.

Me I prefer function style cast... but I think that it should be the


 as
 for
 template so that anyone could write it prefered cast as it is possible


 C++.

 I would also like to have more cast as in C++ where we can explictly


 the compiler which kind of casting we want to allows. In fact, I would

 like to have more cast than in C++. Some of the cast that I think of:

 static_cast            // as in C++
 reinterpret_cast    // low level bit reinterpret
 const_cast            // as in C++ (we should add const support to D)
 dynamic_cast        // base to derived

 implicit_cast        // Allows if cast/conversion is implictly allowed
     without error (and disable any vendor specific warnings)

 range_cast            // Ensure that the value fit in the target

 same_layout_cast    // allowed if the layout is the same (x, y, z vs


     or renamed member)

 enum_cast        // Similar to range cast but only for enums

 fit_cast            // fit to target range (any value lower than target
     min would be set to target min or -INF for floatting points,...)

 ...

 and some more for plateform dependant cast, similar type cast (int to

 ....

 We should have one cast for each kind of casting that can be done...
 and have cast if allowed on the current plateform vs defined exactly
 by the language...

 And I'd like to be able to add my owns...

IMO we should just keep the simple cast (using a "cast(type, value)"

 to reduce the parameters) and have all the other casts as templates. If we
 do it this way we can keep the language clean of one hundred and one new
 keywords and the syntax of templates will certainly improve (just imagine
 dozens of developers frustrated with explicit instantiantion ;). Also
 templates are the standard way to provide generic code (i.e. you would be
 able to add your owns).



 ---
 Outgoing mail is certified Virus Free.
 Checked by AVG anti-virus system (http://www.grisoft.com).
 Version: 6.0.518 / Virus Database: 316 - Release Date: 11/9/2003


Sep 17 2003
parent Felix <Felix_member pathlink.com> writes:
And this approach will be easier to manage in the "intellisense" (code
completion) based editors...


In article <bkbe0c$1gsc$1 digitaldaemon.com>, Felix says...
What about smthng like "variable.doCast(newType)" (standard method call). Yes,
will be more difficult for expressions, but not always:

(variable1+variable2/variable4).doCast(newType)

Me, one, I would preffer this to (newType) (Variable1+Variable2);
It is really necessar to have an operator-based syntax?


Also, other casts should be easier to add.

Yes, and please drop the "_" in function names. Just an innocent idea.



In article <bkav5t$rdo$1 digitaldaemon.com>, Charles Sanders says...
This gets my vote.  Keep the (cast) I vote.

One thing that does worry me, is that there are now a ton of keywords in D,
I realize that there all needed, but what are everyone elses thoughts on
this ?  Id like to keep it to as little as possible.

Charles
"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message
news:bkaqnn$lbt$1 digitaldaemon.com...
 "Philippe Mori" <philippe_mori hotmail.com> escreveu na mensagem
 news:bk9q8l$27ov$1 digitaldaemon.com...
 Any chance of our getting away from the overused round braces in



 and
 adopt something less ambiguous, along the lines of the C++ casts?

 It seems like a retrograde step.

Me I prefer function style cast... but I think that it should be the


 as
 for
 template so that anyone could write it prefered cast as it is possible


 C++.

 I would also like to have more cast as in C++ where we can explictly


 the compiler which kind of casting we want to allows. In fact, I would

 like to have more cast than in C++. Some of the cast that I think of:

 static_cast            // as in C++
 reinterpret_cast    // low level bit reinterpret
 const_cast            // as in C++ (we should add const support to D)
 dynamic_cast        // base to derived

 implicit_cast        // Allows if cast/conversion is implictly allowed
     without error (and disable any vendor specific warnings)

 range_cast            // Ensure that the value fit in the target

 same_layout_cast    // allowed if the layout is the same (x, y, z vs


     or renamed member)

 enum_cast        // Similar to range cast but only for enums

 fit_cast            // fit to target range (any value lower than target
     min would be set to target min or -INF for floatting points,...)

 ...

 and some more for plateform dependant cast, similar type cast (int to

 ....

 We should have one cast for each kind of casting that can be done...
 and have cast if allowed on the current plateform vs defined exactly
 by the language...

 And I'd like to be able to add my owns...

IMO we should just keep the simple cast (using a "cast(type, value)"

 to reduce the parameters) and have all the other casts as templates. If we
 do it this way we can keep the language clean of one hundred and one new
 keywords and the syntax of templates will certainly improve (just imagine
 dozens of developers frustrated with explicit instantiantion ;). Also
 templates are the standard way to provide generic code (i.e. you would be
 able to add your owns).



 ---
 Outgoing mail is certified Virus Free.
 Checked by AVG anti-virus system (http://www.grisoft.com).
 Version: 6.0.518 / Virus Database: 316 - Release Date: 11/9/2003



Sep 17 2003
prev sibling parent "Philippe Mori" <philippe_mori hotmail.com> writes:
 We should have one cast for each kind of casting that can be done...
 and have cast if allowed on the current plateform vs defined exactly
 by the language...

 And I'd like to be able to add my owns...

IMO we should just keep the simple cast (using a "cast(type, value)"

 to reduce the parameters) and have all the other casts as templates. If we
 do it this way we can keep the language clean of one hundred and one new
 keywords and the syntax of templates will certainly improve (just imagine
 dozens of developers frustrated with explicit instantiantion ;). Also
 templates are the standard way to provide generic code (i.e. you would be
 able to add your owns).

I have no problem with having other casts as template provide it is possible to implement the desired cast... Often the compiler knows the information while the programmer might or might not be able to knows it... I think that in D we have more informations on type (like enum range) so we could more easily define some of our cast... but some other might not be easily possible (is it possible to implement static_cast or dynamic_cast using only templates and existing cast by having specialisation for allowed and prohibited cases and ensuring that prohibited cases does not compile? So a minimum is needed to be able to do more... In C++, for example it is hard to detect if a type is a class, an enum, a member pointer, a POD, or to know if a class is abstract... without some support from the compiler. In D, for example, we might want to know if a type is a typedef of another one. Also we might want to be able to check layout compatibity of 2 types: struct S { double x; double y; double z }; alias double [3] Coord; S s; Coord c = layout_cast(s); // I want to compiler to validate that the layout is compatible (and as you can see, specifying the target might not be necessary (but implicit instanciation would be required). In fact, implicit instanciation is required for any user type as we do not want to have to specify both the source and target type... k = my_cast(TargetType, originalValue)
Sep 18 2003
prev sibling next sibling parent reply "Andrew Edwards" <edwardsac spamfreeusa.com> writes:
"Matthew Wilson" <dmd synesis.com.au> wrote in message
news:bk9ln8$21k9$1 digitaldaemon.com...
 Any chance of our getting away from the overused round braces in casts,

 adopt something less ambiguous, along the lines of the C++ casts?

 It seems like a retrograde step.

How about a cast property? double d = 3.14159; printf("%d", d.cast); // outputs 3
Sep 17 2003
next sibling parent reply John Boucher <John_member pathlink.com> writes:
In article <bkaal5$2vat$1 digitaldaemon.com>, Andrew Edwards says...
"Matthew Wilson" <dmd synesis.com.au> wrote in message
news:bk9ln8$21k9$1 digitaldaemon.com...
 Any chance of our getting away from the overused round braces in casts,

 adopt something less ambiguous, along the lines of the C++ casts?

 It seems like a retrograde step.

How about a cast property? double d = 3.14159; printf("%d", d.cast); // outputs 3

Well, you'd still need to tell it what to cast to wouldn't you?: d.cast(int) so what's the difference? And it would be better to have: d.toString(formatstring) d.toInt d.toUInt etc. and all the baggage that follows. John Boucher The King had Humpty pushed.
Sep 17 2003
parent reply "Andrew Edwards" <edwardsac spamfreeusa.com> writes:
"John Boucher" <John_member pathlink.com> wrote in message
news:bkacc2$ar$1 digitaldaemon.com...
 Well, you'd still need to tell it what to cast to wouldn't you?:
 d.cast(int)
 so what's the difference?

format specifiers provides the format of the intended input (in this case int). Upon seeing the cast property, printf should automatically convert d.cast to the expected input. likewise, char [] dstr; char[30] cstr = "Is this even possible?"; dstr = cstr; // error dstr = cstr.cast; // ok the compiler already knows what's expected and will automatally bark at improperly typed inputs or rvalues. Upon seeing cstr.cast however, it should treat cstr as if it were a dynamic string. Andrew
Sep 17 2003
parent "Philippe Mori" <philippe_mori hotmail.com> writes:
 format specifiers provides the format of the intended input (in this case
 int). Upon seeing the cast property, printf should automatically convert
 d.cast to the expected input.

Automatic casting won't works with printf since the format string may not be known to the compiler... and the compiler assumes that the type is correct!
 likewise,

 char [] dstr;
 char[30] cstr = "Is this even possible?";
 dstr = cstr; // error
 dstr = cstr.cast; // ok

 the compiler already knows what's expected and will automatally bark at
 improperly typed inputs or rvalues. Upon seeing cstr.cast however, it

 treat cstr as if it were a dynamic string.

For conversion, I do like the idea... And it would allows conversion that are normally explicit to be done implictly... So something like that should even be possible: int i; bool b = (1 + i).cast; double d; int j = (3.453 * d).cast; int k = d.cast; uint m; if (m == j.cast) // convert j to unsigned for comparison { }
Sep 18 2003
prev sibling parent reply "Dario" <supdar yahoo.com> writes:
I would prefer something like:
.    class A {}
.    class B:A {void func(){}}
.    A b = new B;
.    B.cast(b).func();
Rather than having to write:
.    (cast(B) b).func();
Isn't the former easier to read?

Consider more complex code like the following:
.    ((CK) ((CA) list[i]).kid).func();
That becomes:
.    CK.cast(CA.cast(list[i]).kid).func();


Andrew Edwards:
 How about a cast property?
 double d = 3.14159;
 printf("%d", d.cast); // outputs 3

Matthew Wilson:
 Any chance of our getting away from the overused round braces in casts,

 adopt something less ambiguous, along the lines of the C++ casts?
 It seems like a retrograde step.

Sep 23 2003
next sibling parent reply Ant <Ant_member pathlink.com> writes:
In article <bkq9th$17fn$1 digitaldaemon.com>, Dario says...
.    B.cast(b).func();

Yes! finally something that makes sense! We have been waiting for this for decades. ? b.castTo(B).func() ? Ant
Sep 23 2003
next sibling parent reply Benji Smith <dlanguage xxagg.com> writes:
.    B.cast(b).func();


I hate this one. It looks like your doing something to a "B" object. But you aren't. You're doing something to a "b" object. This syntax is very deceptive.
b.castTo(B).func()

This one, I like. A lot. --Benji
Sep 23 2003
parent "Philippe Mori" <philippe_mori hotmail.com> writes:
.    B.cast(b).func();


I hate this one. It looks like your doing something to a "B" object. But you aren't. You're doing something to a "b" object. This syntax is very deceptive.
b.castTo(B).func()

This one, I like. A lot.

Idem for me. I'd like the second syntax... and it is far better than the suggested on since it does not require too much parenthesis that we must look carefully... In fact, we just have to look inside the () after the predefined castTo method to know what we are casting... and in complex expression, this is surely easier to read than prefix casting.
Sep 23 2003
prev sibling parent reply Antti =?iso-8859-1?Q?Syk=E4ri?= <jsykari gamma.hut.fi> writes:
 In article <bkq9th$17fn$1 digitaldaemon.com>, Dario says...
 I would prefer something like:
    class A {}
    class B:A {void func(){}}
    A b = new B;
    B.cast(b).func();


I stared that for a moment and thought that you surely made a typo there and actually meant to write: b.cast(B).func(); Which kind of makes sense. (similarly as Ant suggested:) In article <bkqaoi$18hk$1 digitaldaemon.com>, Ant wrote:
 Yes! finally something that makes sense!
 We have been waiting for this for decades.

 ? b.castTo(B).func() ?

How about: cast(B, b).func() cast(B: b).func(); cast(B; b).func(); // Syntax a bit similar to foreach(); emphasizes that // cast is not just any function or even cast(b, B).func(); cast(b to B).func(); cast(b as B).func(); cast(b -> B).func(); // too bad -> already has a meaning cast(b: B).func(); cast(B b).func(); cast(B) b.func(); // Java style, huh? (cast(B) b).func(); // What we have now. Cluttered. But for what it's worth, D isn't trying to be Java, so well-written programs contain very few casts anyway and those that remain deserve to stand out. Right? -Antti
Sep 23 2003
next sibling parent reply "Philippe Mori" <philippe_mori hotmail.com> writes:
 Yes! finally something that makes sense!
 We have been waiting for this for decades.

 ? b.castTo(B).func() ?

How about: cast(B, b).func() cast(B: b).func(); cast(B; b).func(); // Syntax a bit similar to foreach(); emphasizes that // cast is not just any function or even cast(b, B).func(); cast(b to B).func(); cast(b as B).func(); cast(b -> B).func(); // too bad -> already has a meaning cast(b: B).func(); cast(B b).func();

In some case like casting the result of a function, I like better f().castTo(double) than cast(double, f()) I'm not sure about the last suggestion but I think that even if it would be possible to uses a syntax without separator it is better to have a separtator (and in my opinion it should be ,) since if both the type and the expression are complex, it is easier to see where one ends and the other start. Also, I like using , as the separator as this is consistent with template...
 cast(B) b.func(); // Java style, huh?

With this syntac as in C++, it is hard to knows where the cast end if the expression is a bit complex and we need extra (). For example, if we want to cast function result...
 (cast(B) b).func(); // What we have now. Cluttered.

 But for what it's worth, D isn't trying to be Java, so well-written
 programs contain very few casts anyway and those that remain deserve to
 stand out. Right?

Cast should be easy to spot and should be easy to understand without needing to count ()... Also the selected syntax should be compatible with templates and should be extendable to user defined cast... If the object.cast syntax is used, then we might want to be able to define our cast to a given type : class C { operator castTo(D) { return ... } operator castTo(E) { return ... } template (T) operator castTo(T) { return member.castTo(T); } } OTHO, if we uses a syntax like cast(B, b), we should be able to define our owns casting functions that works the same way: // Cast and if not possible returns default (just an example) template (T, U) T cast_or_default(U u) { try { return cast(T) u; } catch(...) { return T.init; } }
Sep 23 2003
next sibling parent reply "Sean L. Palmer" <palmer.sean verizon.net> writes:
"Philippe Mori" <philippe_mori hotmail.com> wrote in message
news:bkqfd3$1fkc$1 digitaldaemon.com...
 If the object.cast syntax is used, then we might want to be able
 to define our cast to a given type :

 class C {
     operator castTo(D) { return ... }
     operator castTo(E) { return ... }

     template (T)
     operator castTo(T) { return member.castTo(T); }
 }

Sure! But we would need some official way to accept a _type_ as a function parameter!
 OTHO, if we uses a syntax like cast(B, b), we should be
 able to define our owns casting functions that works the
 same way:

I really don't like this syntax; it's confusing which comes first, the type or the rvalue. Sean
Sep 24 2003
parent "Philippe Mori" <philippe_mori hotmail.com> writes:
 If the object.cast syntax is used, then we might want to be able
 to define our cast to a given type :

 class C {
     operator castTo(D) { return ... }
     operator castTo(E) { return ... }

     template (T)
     operator castTo(T) { return member.castTo(T); }
 }

Sure! But we would need some official way to accept a _type_ as a

 parameter!

I think this would surely be a good thing to accept a type as a function parameter and it would be interesting for metaprogramming. Here a simple example for a factory: class Base { } class Der1 : Base { } class Der2 : Base { } class Der3 : Base { } Base CreateObject(type t, int arg1, int arg2) { return new t(arg1, arg2); } Base a = CreateObject(Der1, 5, 3); Base b = CreateObject(typeof(a), 6, 4); But for casting purpose this is not strictly necessary since in C++ we have conversion operator but we do not have type function parameters: class C { // C++ sample public: // the typename give the operator name. // for complex type a typedef might be required. operator double() const { return 23.4; } // template is even supported... // Here we allows any supported conversion from a member template <typename T> operator T { return member; } M member; }; So IMHO, we should choose the syntax mainly according to the following rules: - easy to uses and to read. - consistent with the language (template, predefine members syntax,...)
 OTHO, if we uses a syntax like cast(B, b), we should be
 able to define our owns casting functions that works the
 same way:

I really don't like this syntax; it's confusing which comes first, the

 or the rvalue.

I see... and with Ant sample, I see why this syntax is not elegant for complex expression in which there are multiples casts...
 Sean

Sep 24 2003
prev sibling parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Philippe Mori wrote:
 If the object.cast syntax is used, then we might want to be able
 to define our cast to a given type :
 
 class C {
     operator castTo(D) { return ... }
     operator castTo(E) { return ... }
 
     template (T)
     operator castTo(T) { return member.castTo(T); }
 }

This introduces the possibility to mess with some assumptions we have about casting. For example, it should be possible to cast the object that is returned by castTo back to the original type. This would have to be explicitly supported by the programmer the returned object. I'm not sure wether this is necessarily such a bad thing, though. After all, operator overloads can always cause stuff like this. On the other hand, this seems like it could get complicated pretty quickly. Imagine the following case: class A { B b; C c; operator castTo(B) { return b; } operator castTo(C) { return c; } }; A a; //This works a.castTo(C); //And this works; a.castTo(B); //Then this should work as well a.castTo(B).castTo(C) So B would not only have to know how it can be casted back to A, but it should also know how to cast to the "sister" interface C. Note that this concept is pretty similar to the way Microsoft's COM and the QueryInterface method works. MS uses this quite a bit to implement interfaces using aggregated objects. Does anyone have sufficient experience with this to offer an opinion on wether it is worth the trouble? Hauke
Sep 24 2003
parent "Philippe Mori" <philippe_mori hotmail.com> writes:
 If the object.cast syntax is used, then we might want to be able
 to define our cast to a given type :

 class C {
     operator castTo(D) { return ... }
     operator castTo(E) { return ... }

     template (T)
     operator castTo(T) { return member.castTo(T); }
 }

This introduces the possibility to mess with some assumptions we have about casting.

In C++, we can define our owns conversion functions... The biggest problem we have in C++ are: - unintended conversion (a conversion that is not always desirable), like the conversion from some string classes to const char * or some automatic pointers classes to the pointer. - ambiguities when a class allows conversion to a class that accept original type in one of its constructor: class A; class B { public: operator A() const; }; class A { public: A (B const &b) { } };
 For example, it should be possible to cast the object that is returned
 by castTo back to the original type. This would have to be explicitly
 supported by the programmer the returned object.

Enven in the language not all casts allows to returns to the original exactly: double d = 1.2; int i = cast(int) d; double d2 = cast(double) i; d will be different than d2 (but in that case, the cast is allowed).
 I'm not sure wether this is necessarily such a bad thing, though. After
 all, operator overloads can always cause stuff like this. On the other
 hand, this seems like it could get complicated pretty quickly. Imagine
 the following case:

 class A
 {
 B b;
 C c;

 operator castTo(B) { return b; }
 operator castTo(C) { return c; }
 };

 A a;

 //This works
 a.castTo(C);

 //And this works;
 a.castTo(B);

 //Then this should work as well
 a.castTo(B).castTo(C)


 So B would not only have to know how it can be casted back to A, but it
 should also know how to cast to the "sister" interface C.

 Note that this concept is pretty similar to the way Microsoft's COM and
 the QueryInterface method works. MS uses this quite a bit to implement
 interfaces using aggregated objects. Does anyone have sufficient
 experience with this to offer an opinion on wether it is worth the

For COM stuff, we need to be able to delegate to the outer object. That is the subobjects b and c need to be able to get the this pointer of the A object that contains them. IMO, the cleanest way to handled that would be to support local classes that have access to the outer class. In such a case, COM compatible casting would be easy to implement provide that cast operator have priority over predefined cast (to ensure that casting to IUnknown or I2 in the example below will return the proper interface). Also for COM programming, with need 2 casting operators: One that do the casting for a given object and one that forward casting to the outer object (otherwise, we would have infinite loops or case where the identity won't be respected (i.e. for I2 we always want to returns either A or C object - not sometime ones and other times the other- and that without depending on the source of the cast). class A : I1, I2 { local class B : I2 { template (T) operator castTo(T) { return outer.castTo(T); } } b; local class C : I3 { template (T) operator castTo(T) { return outer.castTo(T); } } c; operator castTo(I2) { return b.internal_castTo(I2) } operator castTo(I3) { return c.internal_castTo(I3) } } So to implement COM interface casting, which might be great for COM programming, I think we need some extra casting operators. In essence, we need an operator that is called by QueryInterface for each subobject. That operator will then forward to the outer object which will the uses our internal casting. Also we need blind query... but that we be done with a template and verifying the result of the cast....
 Hauke

Sep 24 2003
prev sibling next sibling parent Ant <Ant_member pathlink.com> writes:
In article <slrnbn1eo0.dbp.jsykari pulu.hut.fi>, Antti =?iso-8859-1?Q?Syk=E4ri?=
says...
(similarly as Ant suggested:)

In article <bkqaoi$18hk$1 digitaldaemon.com>, Ant wrote:
 Yes! finally something that makes sense!
 We have been waiting for this for decades.

 ? b.castTo(B).func() ?

How about: cast(B, b).func()

you mean: cast(cast(list[i], B).kid), CK).func() nahhh... same old thing... list[i].castTo(CA).kid.castTo(CK).func() is still better! Ant
Sep 23 2003
prev sibling next sibling parent reply "Sean L. Palmer" <palmer.sean verizon.net> writes:
Nah, Ant's form is better.  Clearer.

b.cast(B).func();

Works even if B is a complicated typespec;  easy to parse;  easy to read.
Self-documenting.

myObjectPtr[n].cast(myFoo*[])[i]->DoFooStuff("foo baby".cast(wchar[]));

This is good.  I like it better than the cast D has now.

DMD still hasn't gotten rid of C's typecast!  I thought the D spec doesn't
support C typecasts?

Sean

"Antti Sykäri" <jsykari gamma.hut.fi> wrote in message
news:slrnbn1eo0.dbp.jsykari pulu.hut.fi...
 In article <bkq9th$17fn$1 digitaldaemon.com>, Dario says...
 I would prefer something like:
    class A {}
    class B:A {void func(){}}
    A b = new B;
    B.cast(b).func();


I stared that for a moment and thought that you surely made a typo there and actually meant to write: b.cast(B).func(); Which kind of makes sense. (similarly as Ant suggested:) In article <bkqaoi$18hk$1 digitaldaemon.com>, Ant wrote:
 Yes! finally something that makes sense!
 We have been waiting for this for decades.

 ? b.castTo(B).func() ?

How about: cast(B, b).func() cast(B: b).func(); cast(B; b).func(); // Syntax a bit similar to foreach(); emphasizes that // cast is not just any function or even cast(b, B).func(); cast(b to B).func(); cast(b as B).func(); cast(b -> B).func(); // too bad -> already has a meaning cast(b: B).func(); cast(B b).func(); cast(B) b.func(); // Java style, huh? (cast(B) b).func(); // What we have now. Cluttered. But for what it's worth, D isn't trying to be Java, so well-written programs contain very few casts anyway and those that remain deserve to stand out. Right? -Antti

Sep 24 2003
parent Felix <Felix_member pathlink.com> writes:
I like this kind of cast. I. e. variable.doCast(newType) etc...



In article <bkrjpa$vg$1 digitaldaemon.com>, Sean L. Palmer says...
Nah, Ant's form is better.  Clearer.

b.cast(B).func();

Works even if B is a complicated typespec;  easy to parse;  easy to read.
Self-documenting.

myObjectPtr[n].cast(myFoo*[])[i]->DoFooStuff("foo baby".cast(wchar[]));

This is good.  I like it better than the cast D has now.

DMD still hasn't gotten rid of C's typecast!  I thought the D spec doesn't
support C typecasts?

Sean

"Antti Sykäri" <jsykari gamma.hut.fi> wrote in message
news:slrnbn1eo0.dbp.jsykari pulu.hut.fi...
 In article <bkq9th$17fn$1 digitaldaemon.com>, Dario says...
 I would prefer something like:
    class A {}
    class B:A {void func(){}}
    A b = new B;
    B.cast(b).func();


I stared that for a moment and thought that you surely made a typo there and actually meant to write: b.cast(B).func(); Which kind of makes sense. (similarly as Ant suggested:) In article <bkqaoi$18hk$1 digitaldaemon.com>, Ant wrote:
 Yes! finally something that makes sense!
 We have been waiting for this for decades.

 ? b.castTo(B).func() ?

How about: cast(B, b).func() cast(B: b).func(); cast(B; b).func(); // Syntax a bit similar to foreach(); emphasizes that // cast is not just any function or even cast(b, B).func(); cast(b to B).func(); cast(b as B).func(); cast(b -> B).func(); // too bad -> already has a meaning cast(b: B).func(); cast(B b).func(); cast(B) b.func(); // Java style, huh? (cast(B) b).func(); // What we have now. Cluttered. But for what it's worth, D isn't trying to be Java, so well-written programs contain very few casts anyway and those that remain deserve to stand out. Right? -Antti


Sep 24 2003
prev sibling parent reply "Dario" <supdar yahoo.com> writes:
Antti Sykäri:
 I stared that for a moment and thought that you surely made a typo there
 and actually meant to write:
 b.cast(B).func();
 Which kind of makes sense.

That wan't a typo! ;-) I thought of that because Ant's version is complicated to parse (function don't get types as parameters). Anyway I am convinced that Ant's version is more intuitive too. I noticed that there are no comments from Walter... Walter, what do you think? You aren't going to keep the prefix cast, are you?
Sep 25 2003
parent reply "Walter" <walter digitalmars.com> writes:
"Dario" <supdar yahoo.com> wrote in message
news:bkvsqs$26e9$1 digitaldaemon.com...
 Antti Sykäri:
 I stared that for a moment and thought that you surely made a typo there
 and actually meant to write:
 b.cast(B).func();
 Which kind of makes sense.

That wan't a typo! ;-) I thought of that because Ant's version is complicated to parse (function don't get types as parameters). Anyway I am convinced that Ant's version is more intuitive too. I noticed that there are no comments from Walter... Walter, what do you think? You aren't going to keep the prefix cast, are you?

The postfix cast does look good, but I don't see it has much advantage over the prefix cast.
Dec 02 2003
next sibling parent reply "Matthew Wilson" <matthew.hat stlsoft.dot.org> writes:
"Walter" <walter digitalmars.com> wrote in message
news:bqjfni$nc0$1 digitaldaemon.com...
 "Dario" <supdar yahoo.com> wrote in message
 news:bkvsqs$26e9$1 digitaldaemon.com...
 Antti Sykäri:
 I stared that for a moment and thought that you surely made a typo



 and actually meant to write:
 b.cast(B).func();
 Which kind of makes sense.

That wan't a typo! ;-) I thought of that because Ant's version is complicated to parse (function don't get types as parameters). Anyway I am convinced that Ant's version is more intuitive too. I noticed that there are no comments from Walter... Walter, what do you think? You aren't going to keep the prefix cast, are you?

The postfix cast does look good, but I don't see it has much advantage

 the prefix cast.

Looks too much like a function call to me. What's wrong with cast(B, b) ? I agree that the prefix cast must die.
Dec 02 2003
next sibling parent reply "Sean L. Palmer" <palmer.sean verizon.net> writes:
"Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message
news:bqjrg3$19kg$1 digitaldaemon.com...
 I noticed that there are no comments from Walter...
 Walter, what do you think? You aren't going to keep the
 prefix cast, are you?

The postfix cast does look good, but I don't see it has much advantage

 the prefix cast.

Looks too much like a function call to me. What's wrong with cast(B, b) ? I agree that the prefix cast must die.

Because it is not immediately obvious which of cast's two parameters are the thing to be casted, and which is the type to cast to. b.cast(B) is much clearer in this regard, which is why everybody was promoting it back then. Apparently Walter is just getting to that discussion. ;) B.cast(b) might work. Either way, it might need to have some extra parenthesis, like this: (new b).cast(B) (B*).cast(b); I wish a good cast syntax would be chosen, but picking one is not easy, it's all bad. Sean
Dec 03 2003
next sibling parent reply "Matthew Wilson" <matthew.hat stlsoft.dot.org> writes:
 I noticed that there are no comments from Walter...
 Walter, what do you think? You aren't going to keep the
 prefix cast, are you?

The postfix cast does look good, but I don't see it has much advantage

 the prefix cast.

Looks too much like a function call to me. What's wrong with cast(B, b)


 I agree that the prefix cast must die.

Because it is not immediately obvious which of cast's two parameters are

 thing to be casted, and which is the type to cast to.

 b.cast(B) is much clearer in this regard, which is why everybody was
 promoting it back then.  Apparently Walter is just getting to that
 discussion.  ;)

 B.cast(b) might work.  Either way, it might need to have some extra
 parenthesis, like this:

 (new b).cast(B)

 (B*).cast(b);

 I wish a good cast syntax would be chosen, but picking one is not easy,

 all bad.

cast<B>(b) ??
Dec 03 2003
parent Georg Wrede <Georg_member pathlink.com> writes:
     a.b.cast(Foo).c.d.cast(Bar).e.f
 is easier to read than:
     (cast(Bar)((cast(Foo)(a.b)).c.d)).e.f

 Bar myBar = a.b;
 Foo myFoo = myBar.c.d;
 myFoo.e.f;

An idea, what if we could write mything = cast(foo)g.cast(bar)h.i.j.cast(baz)k; Then the top example above, if I've understood it correctly, becomes a.cast(Foo)b.c.cast(Bar)d.e.f If we have to do a hairy mix of casts and methods it would still be legible: a.cast(I)b.factMethod(cast(J)c).method(cast(K)d,cast(L)e)
Dec 03 2003
prev sibling next sibling parent davepermen <davepermen_member pathlink.com> writes:
I wish a good cast syntax would be chosen, but picking one is not easy, it's
all bad.

Sean

we just need a good template syntax, and this problem is no problem anymore.. just as static_cast, dynamic_cast, and all behave simply as templated functions in C++. (and that way you could introduce new casts... like com_cast, or any_cast, or lexical_cast..)
Dec 03 2003
prev sibling parent Felix <Felix_member pathlink.com> writes:
Me too, I vote for diff. cast function. As for me, concerning the postfixed
cast, I simply think that a.castTo(B) is best of all...


In article <bqkcal$2365$1 digitaldaemon.com>, Sean L. Palmer says...
"Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message
news:bqjrg3$19kg$1 digitaldaemon.com...
 I noticed that there are no comments from Walter...
 Walter, what do you think? You aren't going to keep the
 prefix cast, are you?

The postfix cast does look good, but I don't see it has much advantage

 the prefix cast.

Looks too much like a function call to me. What's wrong with cast(B, b) ? I agree that the prefix cast must die.

Because it is not immediately obvious which of cast's two parameters are the thing to be casted, and which is the type to cast to. b.cast(B) is much clearer in this regard, which is why everybody was promoting it back then. Apparently Walter is just getting to that discussion. ;) B.cast(b) might work. Either way, it might need to have some extra parenthesis, like this: (new b).cast(B) (B*).cast(b); I wish a good cast syntax would be chosen, but picking one is not easy, it's all bad. Sean

Dec 03 2003
prev sibling next sibling parent Berin Loritsch <bloritsch d-haven.org> writes:
Matthew Wilson wrote:

 
 Looks too much like a function call to me. What's wrong with cast(B, b) ?
 
 I agree that the prefix cast must die.

Umm, here is a simple, but maybe radical idea... why have explicit casts at all? For example, what is wrong with this? CrisisManager crisis = serviceLocater.lookup(CrisisManager.ROLE); SubjectManager subject = serviceLocator.lookup(SubjectManager.ROLE); In both cases, it is perfectly clear what end type is desired. The cast from an object to the end type is all that is needed--which the compiler can take care of. For those times where there may be ambiguity, then we might have to work something out. Either always force the use of a holder variable for the cast to work, or use an "as" keyword like this: printf("Common string embedding %s", myCrisis.getTitle() as char*); That way you avoid unecessary prefix casting or postfix casting looking like a method call.
Dec 03 2003
prev sibling parent Antti =?iso-8859-1?Q?Syk=E4ri?= <jsykari gamma.hut.fi> writes:
In article <bqjrg3$19kg$1 digitaldaemon.com>, Matthew Wilson wrote:
 "Walter" <walter digitalmars.com> wrote in message
 news:bqjfni$nc0$1 digitaldaemon.com...
 "Dario" <supdar yahoo.com> wrote in message
 news:bkvsqs$26e9$1 digitaldaemon.com...
 Antti Sykäri:
 I stared that for a moment and thought that you surely made a typo



 and actually meant to write:
 b.cast(B).func();
 Which kind of makes sense.

That wan't a typo! ;-) I thought of that because Ant's version is complicated to parse (function don't get types as parameters). Anyway I am convinced that Ant's version is more intuitive too. I noticed that there are no comments from Walter... Walter, what do you think? You aren't going to keep the prefix cast, are you?

The postfix cast does look good, but I don't see it has much advantage over the prefix cast.

Looks too much like a function call to me. What's wrong with cast(B, b) ?

Looks like a function call? ;-) But seriously, it does! -Antti
Dec 03 2003
prev sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter wrote:
 The postfix cast does look good, but I don't see it has much advantage over
 the prefix cast.

I like the idea of postfix cast because it makes long chained expressions easier to read. IMHO, this: a.b.cast(Foo).c.d.cast(Bar).e.f is easier to read than: (cast(Bar)((cast(Foo)(a.b)).c.d)).e.f
Dec 03 2003
next sibling parent Berin Loritsch <bloritsch d-haven.org> writes:
Russ Lewis wrote:

 Walter wrote:
 
 The postfix cast does look good, but I don't see it has much advantage 
 over
 the prefix cast.

I like the idea of postfix cast because it makes long chained expressions easier to read. IMHO, this: a.b.cast(Foo).c.d.cast(Bar).e.f is easier to read than: (cast(Bar)((cast(Foo)(a.b)).c.d)).e.f

Honestly, I don't like having to type cast() at all. Although I agree that the example you had would look equally ugly in Java code: ((Bar)((Foo)a).b).c.d.e.f However, such a construct is not common IMO. At most there would be only one cast needed: ((Foo)mycollection.get("Foo")).doSomething(); And IMO, it would be even better to do something like this: Foo myfoo = mycollection.get("Foo"); myfoo.doSomething(); It is more clear that is what is going on, as opposed to placing the two method calls on the same line--in such a way that would fool sloc counters....
Dec 03 2003
prev sibling next sibling parent reply Berin Loritsch <bloritsch d-haven.org> writes:
Russ Lewis wrote:

 Walter wrote:
 
 The postfix cast does look good, but I don't see it has much advantage 
 over
 the prefix cast.

I like the idea of postfix cast because it makes long chained expressions easier to read. IMHO, this: a.b.cast(Foo).c.d.cast(Bar).e.f is easier to read than: (cast(Bar)((cast(Foo)(a.b)).c.d)).e.f

How about this instead: Bar myBar = a.b; Foo myFoo = myBar.c.d; myFoo.e.f; It forces you to break up the expression into something less confusing and ends up being easier to read. Of course I would prefer to use "as" instead of "cast" if we had to clarify things. a.b.as(Foo).c.b.as(Bar).e.f; I just have trouble envisioning this need....
Dec 03 2003
next sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Berin Loritsch wrote:
 Russ Lewis wrote:
 
 Walter wrote:

 The postfix cast does look good, but I don't see it has much 
 advantage over
 the prefix cast.

I like the idea of postfix cast because it makes long chained expressions easier to read. IMHO, this: a.b.cast(Foo).c.d.cast(Bar).e.f is easier to read than: (cast(Bar)((cast(Foo)(a.b)).c.d)).e.f

How about this instead: Bar myBar = a.b; Foo myFoo = myBar.c.d; myFoo.e.f;

I use either one-line or multi-line solutions, based on which is more readable. In some scenarios, one is better; in others, the other. However, IMHO, prefix cast almost *forces* you to use multiple lines. That means that, sometimes, the code is less readable than it would have been if the language had been more flexible.
 It forces you to break up the expression into something less confusing
 and ends up being easier to read.
 
 Of course I would prefer to use "as" instead of "cast" if we had to
 clarify things.
 
 a.b.as(Foo).c.b.as(Bar).e.f;
 
 I just have trouble envisioning this need....

I have run across it more than once. Two casts is rare, but having one cast, followed by some member accesses or method calls, is not unusual.
Dec 03 2003
prev sibling parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Berin Loritsch wrote:
 I like the idea of postfix cast because it makes long chained 
 expressions easier to read.  IMHO, this:
     a.b.cast(Foo).c.d.cast(Bar).e.f
 is easier to read than:
     (cast(Bar)((cast(Foo)(a.b)).c.d)).e.f

How about this instead: Bar myBar = a.b; Foo myFoo = myBar.c.d; myFoo.e.f; It forces you to break up the expression into something less confusing and ends up being easier to read.

That might be true for some situations, but this has the potential to get annoying in others. For example, you cannot take the return value of one function, cast it and directly pass it into another. Having to use temporaries all the time can be a bad thing. And it can also make code less readable by adding lots of unnecessary lines of code and locals that do not really serve a purpose. Also, I suspect (though I'm not sure) that this could make optimizing (particularly inlining) harder for the compiler. At the very least it will increase the compile time, because there are more local vars to consider. Also, such an implicit casting would water down D's strong type checking, which is a Bad Thing, IMHO. The postfix cast gets my vote! Hauke
Dec 03 2003
parent reply Berin Loritsch <bloritsch d-haven.org> writes:
Hauke Duden wrote:
 Berin Loritsch wrote:
 
 I like the idea of postfix cast because it makes long chained 
 expressions easier to read.  IMHO, this:
     a.b.cast(Foo).c.d.cast(Bar).e.f
 is easier to read than:
     (cast(Bar)((cast(Foo)(a.b)).c.d)).e.f

How about this instead: Bar myBar = a.b; Foo myFoo = myBar.c.d; myFoo.e.f; It forces you to break up the expression into something less confusing and ends up being easier to read.

That might be true for some situations, but this has the potential to get annoying in others. For example, you cannot take the return value of one function, cast it and directly pass it into another. Having to use temporaries all the time can be a bad thing. And it can also make code less readable by adding lots of unnecessary lines of code and locals that do not really serve a purpose.

Not necessarily. As long as there is no ambiguity, the implicit cast should continue to work: interface Bar {} int foo(Bar baz) { return 1; } class SubClass : Bar {} // .... in client code later on foo( new SubClass() ); // or foo( getInstance() ); // returning SubClass or other impl of Bar
 
 Also, I suspect (though I'm not sure) that this could make optimizing 
 (particularly inlining) harder for the compiler. At the very least it 
 will increase the compile time, because there are more local vars to 
 consider.

If that is the case, the compiler is not very good.
 Also, such an implicit casting would water down D's strong type 
 checking, which is a Bad Thing, IMHO.
 
 The postfix cast gets my vote!

I don't think so. We are not talking about operator overloading here which waters it down for real. What we are talking about is leveraging the strong typing so that you can never *upcast*. One danger in allowing upcasts (i.e. casting to an interface/type that is higher in the heirarchy) is that you are no longer working with those types. This is the source of many ClassCastExceptions in Java. Another issue has to do with hijacking responsibility. For instance, if I have a component that I give a lookup service to, I want to be able to ensure no other component can hijack that lookup service. I have some Java code that demonstrates that issue--which can easily be thwarted with proxies. The only upcast that should ever work is one from the generic object type to an Interface. Once there is a definite type, no more upcasting. Then again, this might fall under the half-baked idea column. This comes from my loathing to type the cast all the time when my intention is only to use the interface as is. I would be more than willing to use generics, but there is no way to use generics when the return type is different depending on the lookup key.
Dec 03 2003
parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Berin Loritsch wrote:
 Not necessarily.  As long as there is no ambiguity, the implicit cast 
 should
 continue to work:
 
 interface Bar {}
 
 int foo(Bar baz)
 {
     return 1;
 }
 
 class SubClass : Bar {}
 
 // .... in client code later on
 
 foo( new SubClass() );
 
 // or
 
 foo( getInstance() ); // returning SubClass or other impl of Bar

I think there is some kind of misunderstanding. If getInstance() returns a sub class of Bar, then there will be no cast necessary, because the returned object already is of the correct type.
 What we are talking about is leveraging the strong typing so that you
 can never *upcast*.

Ah. I think I understand what you want. You just want to remove casting altogether, thus only allowing what you call "implicit casts", i.e. casts to a base type? Wouldn't work. For example, sometimes you just have to pass a sub class thorugh a program component that only knows the base class and cast it back up to the original type afterwards. Btw, what *I* thought you meant is to use temporary variables to perform a real cast. I.e. allow assigning any type to a local variable when that variable is constructed: Bar getBar(); void setFoo(Foo foo); Foo foo=getBar(); but not setFoo(getBar()); for unrelated types Foo and Bar. THAT would water down D's type system!
 The only upcast that should ever work is one from the generic object type
 to an Interface.  Once there is a definite type, no more upcasting.

That would just make casting harder, since you'd first have to cast down to Object and then back up to the class you want. Hauke
Dec 03 2003
parent reply Berin Loritsch <bloritsch d-haven.org> writes:
Hauke Duden wrote:

 Berin Loritsch wrote:
 
 What we are talking about is leveraging the strong typing so that you
 can never *upcast*.

Ah. I think I understand what you want. You just want to remove casting altogether, thus only allowing what you call "implicit casts", i.e. casts to a base type? Wouldn't work. For example, sometimes you just have to pass a sub class thorugh a program component that only knows the base class and cast it back up to the original type afterwards.

Bad code. Shouldn't do it. More often than not, upcasting from a base type other than the generic "object" is a poor substitute for what you really want. That's what interfaces are for. You specify your contracts in the interface, and pass your object so that the code uses the interface AND NOTHING ELSE.
 Btw, what *I* thought you meant is to use temporary variables to perform 
 a real cast. I.e. allow assigning any type to a local variable when that 
 variable is constructed:
 
 Bar getBar();
 void setFoo(Foo foo);
 
 Foo foo=getBar();
 
 but not
 
 setFoo(getBar());
 
 for unrelated types Foo and Bar.
 
 THAT would water down D's type system!

Please, no.
 The only upcast that should ever work is one from the generic object type
 to an Interface.  Once there is a definite type, no more upcasting.

That would just make casting harder, since you'd first have to cast down to Object and then back up to the class you want.

That is the point. Some things like collections *have* to use Object, so at that time you upcast to the interface you want. Notice, that I limited the upcast from object to interfaces? Granted this would nicely fit the way I work--but not everyone in the world.
Dec 03 2003
parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Berin Loritsch wrote:
 Wouldn't work. For example, sometimes you just have to pass a sub 
 class thorugh a program component that only knows the base class and 
 cast it back up to the original type afterwards.

Bad code. Shouldn't do it. More often than not, upcasting from a base type other than the generic "object" is a poor substitute for what you really want.

That is a pretty sweeping statement you make there. Here's an example against that: Consider an image manupulation algorithm that takes quite a while. It takes a bunch of objects of type Bitmap and works on them. However, YOUR bitmaps are of the type BitmapWithName, which is derived from Bitmap. The algorithm calls a progress function regularly, in which you update your GUI to reflect the progress. The current bitmap the algorithm works on is passed to that function, as a Bitmap reference. Since you want to display the name of the current bitmap and you know that all objects you feed the algorithm are your own BitmapWithName objects, you have to cast the object you get up to that class, in order to retrieve its name. Presto: an upcast from a class other than Object. Hauke
Dec 03 2003
parent reply Berin Loritsch <bloritsch d-haven.org> writes:
Hauke Duden wrote:
 Berin Loritsch wrote:
 
 Wouldn't work. For example, sometimes you just have to pass a sub 
 class thorugh a program component that only knows the base class and 
 cast it back up to the original type afterwards.

Bad code. Shouldn't do it. More often than not, upcasting from a base type other than the generic "object" is a poor substitute for what you really want.

That is a pretty sweeping statement you make there. Here's an example against that:

;P You noticed?
 
 Consider an image manupulation algorithm that takes quite a while. It 
 takes a bunch of objects of type Bitmap and works on them. However, YOUR 
 bitmaps are of the type BitmapWithName, which is derived from Bitmap.
 
 The algorithm calls a progress function regularly, in which you update 
 your GUI to reflect the progress. The current bitmap the algorithm works 
 on is passed to that function, as a Bitmap reference. Since you want to 
 display the name of the current bitmap and you know that all objects you 
 feed the algorithm are your own BitmapWithName objects, you have to cast 
 the object you get up to that class, in order to retrieve its name.
 
 Presto: an upcast from a class other than Object.

Counter example: You know that somethimes there will be objects that must be namable, so you create an interface to represent that concern called "Namable" which essentially consists of a getName() method. Your new BitmapWithName object implements the Bitmap and Namable interfaces. The Progress function performs something like this: char[] name = ""; if ( progressiveObject instanceof Nameable ) { Nameable obj = progressiveObject; name = obj.getName(); } At least that is what you do in Java. If you make your contract directly with an Object, your code is bound to that object. If that object is horribly written and is cast aside later on your code will break in many unexpected ways. However if you make a contract with an interface, ANY object that implements that interface can be used. In fact your functions become more flexible and reusable because the progress function no longer expects to deal with Bitmap objects, but anything that can be namable.
Dec 04 2003
parent Hauke Duden <H.NS.Duden gmx.net> writes:
Berin Loritsch wrote:
 Presto: an upcast from a class other than Object.

Counter example: You know that somethimes there will be objects that must be namable, so you create an interface to represent that concern called "Namable" which essentially consists of a getName() method. Your new BitmapWithName object implements the Bitmap and Namable interfaces.

That would work too, but you cannot FORCE programmers to use interfaces for everything. In particular, if you just need a quick prototype (for example, for a demo that needs to be done yesterday) you'd probably want the option to just declare the functionality you need directly in the object class, without having to define additional interfaces. Also, right now there is a serious limitation to D's interfaces that pretty much prevents them from being used in that way. I always wanted to write an longer post about this issue, but never got around to it. The main problem is that if a class implements an interface A and a derived class wants to implement a sub-interface "B" of A, then you have to re-implement all the functions of A again (probably with stubs that call the base class). This is a serious issue if you build an interface hierarchy and want to reuse an existing implementation of a base-interface as a basis for an implementation of a more specific interface (which you often want!). You end up writing dozens of stub-methods that do nothing except calling the base class implementation, for each and every class and every interface it implements. I'll try to write the post on that topic tonight, with a better explanation of what I mean. This issue is actually pretty important to me, even critical for my decision of whether I'll ever switch to D. So I want to make sure that my point is understandable. Hauke
Dec 04 2003
prev sibling next sibling parent Ant <Ant_member pathlink.com> writes:
In article <bql580$4ki$1 digitaldaemon.com>, Russ Lewis says...
Walter wrote:
 The postfix cast does look good, but I don't see it has much advantage over
 the prefix cast.

I like the idea of postfix cast because it makes long chained expressions easier to read. IMHO, this: a.b.cast(Foo).c.d.cast(Bar).e.f is easier to read than: (cast(Bar)((cast(Foo)(a.b)).c.d)).e.f

I like castTo better because is more explicit and avoids confusion for someone used to older languages. a.b.castTo(Foo).c.d.castTo(Bar).e.f Ant
Dec 03 2003
prev sibling parent reply "Matthew Wilson" <matthew.hat stlsoft.dot.org> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:bql580$4ki$1 digitaldaemon.com...
 Walter wrote:
 The postfix cast does look good, but I don't see it has much advantage


 the prefix cast.

I like the idea of postfix cast because it makes long chained expressions easier to read. IMHO, this: a.b.cast(Foo).c.d.cast(Bar).e.f is easier to read than: (cast(Bar)((cast(Foo)(a.b)).c.d)).e.f

Hmmm. There's some mileage in the C++ philosophy of not facilitating the ease-of-expression; maybe casts should be nasty to type?
Dec 03 2003
parent Ant <Ant_member pathlink.com> writes:
In article <bqmiig$2901$1 digitaldaemon.com>, Matthew Wilson says...
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:bql580$4ki$1 digitaldaemon.com...
 Walter wrote:
 The postfix cast does look good, but I don't see it has much advantage


 the prefix cast.

I like the idea of postfix cast because it makes long chained expressions easier to read. IMHO, this: a.b.cast(Foo).c.d.cast(Bar).e.f is easier to read than: (cast(Bar)((cast(Foo)(a.b)).c.d)).e.f

Hmmm. There's some mileage in the C++ philosophy of not facilitating the ease-of-expression; maybe casts should be nasty to type?

You might be right but anyway you cut it shoud be easy to read, that's the only advantage we a seeking with the postfix idea. Ant
Dec 04 2003
prev sibling parent Ant <Ant_member pathlink.com> writes:
In article <bkq9th$17fn$1 digitaldaemon.com>, Dario says...
I would prefer something like:
.    class A {}
.    class B:A {void func(){}}
.    A b = new B;
.    B.cast(b).func();
Rather than having to write:
.    (cast(B) b).func();
Isn't the former easier to read?

Consider more complex code like the following:
.    ((CK) ((CA) list[i]).kid).func();
That becomes:
.    CK.cast(CA.cast(list[i]).kid).func();

list[i].castTo(CA).kid.castTo(CK).funct or list[i].cast(CA).kid.cast(CK).funct or list[i].to(CA).kid.to(CK).funct looks even better to me! and list[i].castTo(MyClass*) looks better then Class*.cast(list[i]) or (Class*).cast(list[i]) Ant
Sep 23 2003
prev sibling parent Robert <Robert_member pathlink.com> writes:
from:  D/19990

I've remembered that I thought about cast expression this April
(but independently of D,)
and have found the memo which was written then.


I introduced two types of *postfix* cast in the memo.
One is `down_cast' for down cast and another is `cast' for the other cast
(exactly I introduced also `up_cast' for the case of multiple inheritance.)

e.g.)
A a = new A;
B b = a.cast(B);
C c = a.down_cast(D);

The memo also says as follows:

Casts are similar to constructors,
but casts are opposite processes to constructors.
Because "A a = new A; B b = a.cast(B);" makes
B's instance from A's instance though the `cast' is A's member function.
It gives the same result as new B(a) (if B(A) is defined,)
however, the cast can be implemented even if B knows *nothing* about A.
This is a very important aspect of casts,
and supports that casts must be subject to the casted classes.

Casts are treated as member functions, but the syntax is special.
Because return value types are given from the arguments.
It's a unique property of casts.
Many cast functions seem to have no arguments (the same arguments),
but they can be overloaded.

`implicit' keyword allows implicit cast if not ambiguous.
Overloaded casts should be explicit by default.

e.g.)
struct Point {
public int x, y;
public Size cast() {
return new Size(x, y);
}
public implicit LongPoint cast() {
return new LongPoint(x, y);
}
}
Point pt;
Size siz = pt.cast(size);
LongPoint lpt = pt;

Cast methods can have some additional arguments if necessary.

Down casts must be treated with especial care,
must not be overloaded, and make no instances,
so they should be distinguished from normal casts and
should be done with special keyword.


Though some specs may be bizarre,
I would appreciate hearing advices for it.

Robert (Japanese)
Dec 07 2003