www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Overloading opCast with multiple types

reply Reiner Pope <reiner.pope REMOVE.THIS.gmail.com> writes:
As we all know, opCast can only have one overload per class, because D 
doesn't support overloading by return type. That is a really silly 
limitation, in my opinion. Anyway, I have a solution here: give it a 
parameter, which is the type (we pass this parameter in the form of a 
template). Here's the magic:

class Test
{
	int x;
	Foo myCast(TFoo : Foo)() { static assert(is(TFoo == Foo), "No cast of 
the required type exists"); return new Foo(x); }
	Bar myCast(TBar : Bar)() { static assert(is(TBar == Bar),  "No cast of 
the required type exists"); return new Bar(x); }
	FooExtender2 myCast(T : FooExtender2)() { static assert(is(T == 
FooExtender2), "No cast of the required type exists"); return new 
FooExtender2(x); }
	this(int _x) {x = _x;}
}

and it is called like this:

	Test a = new Test(5);
	Foo f = a.myCast!(Foo); // Property syntax means the second () is 
unnecessary, so it looks almost like cast(Foo)a;
	Bar b = a.myCast!(Bar);
//	Useless u = a.myCast!(Useless); // Fails -- no template 
specialization exists
//	FooExtender t = a.myCast!(FooExtender); // Fails the static assert 
(TFoo == Foo)

This code works right now. The static asserts are necessary because 
template specialization doesn't have the expressiveness of is 
expressions. I want the ability to say, "use this specialization for 
this type only, and don't use it for the subtypes."

If this were supported under opCast, I would say that it should work by 
using templates as I have above, and adding a specialization type, so 
that templates could look like this: myCast(TFoo == Foo)() { return new 
Foo(x); }. (The '==' syntax is the noteworthy bit)

Let me know what you think,

Reiner
Sep 30 2006
next sibling parent reply Kristian <kjkilpi gmail.com> writes:
On Sun, 01 Oct 2006 01:25:15 +0300, Reiner Pope  =

<reiner.pope REMOVE.THIS.gmail.com> wrote:
 As we all know, opCast can only have one overload per class, because D=

 doesn't support overloading by return type. That is a really silly  =

 limitation, in my opinion. Anyway, I have a solution here: give it a  =

 parameter, which is the type (we pass this parameter in the form of a =

 template). Here's the magic:

 class Test
 {
 	int x;
 	Foo myCast(TFoo : Foo)() { static assert(is(TFoo =3D=3D Foo), "No cas=

 the required type exists"); return new Foo(x); }
 	Bar myCast(TBar : Bar)() { static assert(is(TBar =3D=3D Bar),  "No ca=

 the required type exists"); return new Bar(x); }
 	FooExtender2 myCast(T : FooExtender2)() { static assert(is(T =3D=3D  =

 FooExtender2), "No cast of the required type exists"); return new  =

 FooExtender2(x); }
 	this(int _x) {x =3D _x;}
 }

Actually I was thinking something similar a while ago. Then I thought th= at = maybe there is only one opCast() for a reason. And you could use functio= ns = as 'toString()' to do the casting (but, yeah, that's explicit). Anyway, I think the opCasts can also be implemented as follows: class Obj { int opCast(out int dst) {return(dst =3D ...);} Foo opCast(out Foo dst) {return(dst =3D ...);} } Or in some other way which don't complicate the implementation of = compilers. (Of course, the previous syntax makes it cumbersome to call = opCasts by yourself (e.g. "obj.opCast(tmp);"), but you're supposed to us= e = cast statements anyway (e.g. "cast(int)obj").) Finally I have to say that I think the implicit type casting in C++ coul= d = work better. For example: class String { operator int() const; operator char *() const; }; void func(int v); void func(char *s); String s; func(s); //error: ambigious call Because 'String' can be casted to 'int' and 'char *', the compiler don't= = know which one to use. Of course, 's' should be casted to 'char *' becau= se = the class represents a string (i.e. 'char *'). This could be solved by using some kind of preference ordering. For = example (don't pay attention to the syntax): class String { preference 2 operator int() const; preference 1 operator char *() const; //prefer 'char *' over 'int'= }; So, if D will have multiple opCasts along with the implicit type = conversion, maybe something similar could be used to solve problems with= = implicit casting.
Oct 01 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Kristian" <kjkilpi gmail.com> wrote in message 
news:op.tgqne1b35xlco7 mist...

-------------------------------------------
Anyway, I think the opCasts can also be implemented as follows:

class Obj {
     int opCast(out int dst) {return(dst = ...);}
     Foo opCast(out Foo dst) {return(dst = ...);}
}

Or in some other way which don't complicate the implementation of
compilers. (Of course, the previous syntax makes it cumbersome to call
opCasts by yourself (e.g. "obj.opCast(tmp);"), but you're supposed to use
cast statements anyway (e.g. "cast(int)obj").)
--------------------------------------------

Of course, with that method, something like

Obj o = new Obj();
func(cast(int)o);

Wouldn't work, because there is no location to pass into the opCast; it's 
just a temporary.

I've gotten quite used to just having ".toXXX" or ".asXXX" methods.  It can 
be far more obvious what you're doing, and you can pass additional 
parameters to it unlike a cast.  That, and it can look nicer too:

int x = (cast(ArrayType)object)[4];

vs

int x = object.asArrayType[4]; 
Oct 01 2006
parent reply Kristian <kjkilpi gmail.com> writes:
On Sun, 01 Oct 2006 18:24:50 +0300, Jarrett Billingsley  =

<kb3ctd2 yahoo.com> wrote:
 "Kristian" <kjkilpi gmail.com> wrote in message
 news:op.tgqne1b35xlco7 mist...

 -------------------------------------------
 Anyway, I think the opCasts can also be implemented as follows:

 class Obj {
      int opCast(out int dst) {return(dst =3D ...);}
      Foo opCast(out Foo dst) {return(dst =3D ...);}
 }

 Or in some other way which don't complicate the implementation of
 compilers. (Of course, the previous syntax makes it cumbersome to call=

 opCasts by yourself (e.g. "obj.opCast(tmp);"), but you're supposed to =

 cast statements anyway (e.g. "cast(int)obj").)
 --------------------------------------------

 Of course, with that method, something like

 Obj o =3D new Obj();
 func(cast(int)o);

 Wouldn't work, because there is no location to pass into the opCast; i=

 just a temporary.

Well yes, unless the compiler generates a temporary object that will be = = valid within the scope. For example, the previous example, will become: int _tmp; Obj o =3D new Obj(); func(o.opCast(_tmp)); The syntax of opCast() is a matter of implementation only: which is the = = simpliest way for the compiler. If not, then the C++ styled operators = could be used in D also. BTW, you could also have: class Obj { int opCast(int) {return(...);} Foo opCast(Foo) {return(...);} } Parameters are just used to overload the operators.
 I've gotten quite used to just having ".toXXX" or ".asXXX" methods.  I=

 can
 be far more obvious what you're doing, and you can pass additional
 parameters to it unlike a cast.  That, and it can look nicer too:

 int x =3D (cast(ArrayType)object)[4];

 vs

 int x =3D object.asArrayType[4];

Yep, I also prefer such functions over cast statements. But if D would have implicit type conversion with multiple opCasts, then= = you could just do "x =3D y;". Would this be a good thing?... I don't kno= w. = (Surely it would be less informative, if nothing else.)
Oct 01 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Kristian" <kjkilpi gmail.com> wrote in message 
news:op.tgq6xi1s5xlco7 mist...
---------------------------------------------
Yep, I also prefer such functions over cast statements.
But if D would have implicit type conversion with multiple opCasts, then
you could just do "x = y;". Would this be a good thing?... I don't know.
(Surely it would be less informative, if nothing else.)
---------------------------------------------

(my newsreader does not like quoting your posts for some reason!)

Walter has expressed his.. disgust?  Lack of support?  for C++-style 
implicit casts, and I agree with him to an extent.  For trying to make 
"value" types (such as a BigInteger class or something), not having implicit 
casts can make it cumbersome to use the class, but to be honest, I've never 
had to write such a type.

In any case, I wouldn't cross my fingers for anything like this to happen 
soon ;) 
Oct 01 2006
parent reply Georg Wrede <georg.wrede nospam.org> writes:
Jarrett Billingsley wrote:
 "Kristian" <kjkilpi gmail.com> wrote in message 
 news:op.tgq6xi1s5xlco7 mist...
 ---------------------------------------------
 Yep, I also prefer such functions over cast statements.
 But if D would have implicit type conversion with multiple opCasts, then
 you could just do "x = y;". Would this be a good thing?... I don't know.
 (Surely it would be less informative, if nothing else.)
 ---------------------------------------------
 
 (my newsreader does not like quoting your posts for some reason!)

In addition to quoting difficulties, are you not familiar with the security and usage issues Microsoft Outlook Express v 6 has? Most other people here are already using something else.
Oct 01 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Georg Wrede" <georg.wrede nospam.org> wrote in message 
news:45203A8F.6030800 nospam.org...
 In addition to quoting difficulties, are you not familiar with the 
 security and usage issues Microsoft Outlook Express v 6 has?

 Most other people here are already using something else.

Man, I'd better just go with the flow, hm? I sure don't want to be left out. This is the only newsgroup I read, and Kristian is the only user whose posts don't quote right. I think I can live with OE.
Oct 01 2006
parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Sun, 1 Oct 2006 18:59:00 -0400, Jarrett Billingsley wrote:

 "Georg Wrede" <georg.wrede nospam.org> wrote in message 
 news:45203A8F.6030800 nospam.org...
 In addition to quoting difficulties, are you not familiar with the 
 security and usage issues Microsoft Outlook Express v 6 has?

 Most other people here are already using something else.

Man, I'd better just go with the flow, hm? I sure don't want to be left out. This is the only newsgroup I read, and Kristian is the only user whose posts don't quote right. I think I can live with OE.

LOL... I used to think that way too until I actually tried a purpose-built newsreader that adhered to standards. I'll never go back to that toy newsreader again. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 2/10/2006 10:01:16 AM
Oct 01 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Derek Parnell" <derek nomail.afraid.org> wrote in message 
news:96d4ls69hbtj.cdpdafq3hhs3.dlg 40tude.net...

 LOL... I used to think that way too until I actually tried a purpose-built
 newsreader that adhered to standards. I'll never go back to that toy
 newsreader again.

Thing is, I tried Thunderbird, and .. I couldn't really tell a difference from OE. Except that it was slower. Are there any other good free readers for Windows then?
Oct 02 2006
next sibling parent Kristian <kjkilpi gmail.com> writes:
On Mon, 02 Oct 2006 23:21:37 +0300, Jarrett Billingsley  
<kb3ctd2 yahoo.com> wrote:

 "Derek Parnell" <derek nomail.afraid.org> wrote in message
 news:96d4ls69hbtj.cdpdafq3hhs3.dlg 40tude.net...

 LOL... I used to think that way too until I actually tried a  
 purpose-built
 newsreader that adhered to standards. I'll never go back to that toy
 newsreader again.

Thing is, I tried Thunderbird, and .. I couldn't really tell a difference from OE. Except that it was slower. Are there any other good free readers for Windows then?

Well, I have been using Opera and it has been working fine (in addition, I like to surf and read NGs with the same program). Though it took a while to setup the digitalmars NGs: Opera didn't connect to the NG server right away.
Oct 03 2006
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Jarrett Billingsley wrote:
 "Derek Parnell" <derek nomail.afraid.org> wrote in message 
 news:96d4ls69hbtj.cdpdafq3hhs3.dlg 40tude.net...
 
 LOL... I used to think that way too until I actually tried a purpose-built
 newsreader that adhered to standards. I'll never go back to that toy
 newsreader again.

Thing is, I tried Thunderbird, and .. I couldn't really tell a difference from OE. Except that it was slower.

(Had this in my drafts folder for a while, keep meaning to post it!) Whenever I've moved from OE to anything else, one of the first things I've noticed is freedom from OE's many annoying bugs. How many of these bit you? http://www.epinions.com/content_67328904836 OK, so other newsreaders have bugs too, but not many have an array of bugs that's quite as annoying as this.
 Are there any other good free readers for Windows then? 

How different is Thunderbird from the newsreader facilities of Mozilla Application Suite/SeaMonkey (which I use)? Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- C++ a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Oct 23 2006
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message 
news:ehijj9$1r6d$3 digitaldaemon.com...to post it!)
 Whenever I've moved from OE to anything else, one of the first things
 I've noticed is freedom from OE's many annoying bugs.  How many of these
 bit you?

 http://www.epinions.com/content_67328904836

None, actually. I only have one news server so I don't have trouble with it posting to the wrong server; I don't have a signature; and I don't use any of the watch/ignore/view features. The only problem I've ever run into is the random not-quoting bug. So from my experience, it's OK for me :)
 How different is Thunderbird from the newsreader facilities of Mozilla
 Application Suite/SeaMonkey (which I use)?

I've heard some people talking about SeaMonkey and how they like it. I'll have to check it out sometime.
Oct 23 2006
prev sibling next sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Reiner Pope wrote:
 As we all know, opCast can only have one overload per class, because D 
 doesn't support overloading by return type. That is a really silly 
 limitation, in my opinion. Anyway, I have a solution here: give it a 
 parameter, which is the type (we pass this parameter in the form of a 
 template). Here's the magic:
 
 class Test
 {
     int x;
     Foo myCast(TFoo : Foo)() { static assert(is(TFoo == Foo), "No cast 
 of the required type exists"); return new Foo(x); }

Something to this effect has been proposed before. However, the idea of having to put a static assert in each would make it somewhat more cumbersome than it should be. Moreover, a problem with using templates is deciding how the vtbl would work. There have been a number of proposals for ways to do multiple casts. http://www.prowiki.org/wiki4d/wiki.cgi?FeatureRequestList My proposal: http://tinyurl.com/p2pn4 Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- C++ a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Oct 01 2006
parent reply pragma <ericanderton yahoo.com> writes:
Stewart Gordon wrote:
 Reiner Pope wrote:
 As we all know, opCast can only have one overload per class, because D 
 doesn't support overloading by return type. That is a really silly 
 limitation, in my opinion. Anyway, I have a solution here: give it a 
 parameter, which is the type (we pass this parameter in the form of a 
 template). Here's the magic:

 class Test
 {
     int x;
     Foo myCast(TFoo : Foo)() { static assert(is(TFoo == Foo), "No cast 
 of the required type exists"); return new Foo(x); }

Something to this effect has been proposed before. However, the idea of having to put a static assert in each would make it somewhat more cumbersome than it should be. Moreover, a problem with using templates is deciding how the vtbl would work. There have been a number of proposals for ways to do multiple casts. http://www.prowiki.org/wiki4d/wiki.cgi?FeatureRequestList My proposal: http://tinyurl.com/p2pn4 Stewart.

Well, while we're on the topic, I might as well mention this variant as well. :) class Foobar{ void* opCast(TypeInfo type){ /* perform cast and return instance/value as needed } } Not only does this play fair with D's overload rules (no overload by return type) but it handles every possible case for casting, and IMO, is no more cumbersome than varargs are. For what it's worth, the runtime already does something similar when a dynamic cast is required.
Oct 02 2006
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
pragma wrote:
<snip>
 Well, while we're on the topic, I might as well mention this variant as 
 well. :)
 
 class Foobar{
   void* opCast(TypeInfo type){
     /* perform cast and return instance/value as needed
   }
 }

How can you return an artibrary value as a void*? Besides, it looks exactly like what you proposed ages ago and I've already critiqued, as you'd know if you'd read what I linked to. Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- C++ a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Oct 03 2006
parent Pragma <ericanderton yahoo.removeme.com> writes:
Stewart Gordon wrote:
 pragma wrote:
 <snip>
 Well, while we're on the topic, I might as well mention this variant 
 as well. :)

 class Foobar{
   void* opCast(TypeInfo type){
     /* perform cast and return instance/value as needed
   }
 }

How can you return an artibrary value as a void*? Besides, it looks exactly like what you proposed ages ago and I've already critiqued, as you'd know if you'd read what I linked to. Stewart.

Mea culpa. Sometimes, some ideas are hard to let go. :) -- - EricAnderton at yahoo
Oct 03 2006
prev sibling parent reply Kristian <kjkilpi gmail.com> writes:
On Sun, 01 Oct 2006 01:25:15 +0300, Reiner Pope  
<reiner.pope REMOVE.THIS.gmail.com> wrote:

 As we all know, opCast can only have one overload per class, because D  
 doesn't support overloading by return type. That is a really silly  
 limitation, in my opinion.

I think it's not important to consider how overloadable opCasts can be implemented. The documentation indeed states "Since functions cannot be overloaded based on return value, there can be only one opCast per struct or class.", but that's not the actual reason why there is only one opCast. It may be a practical reason (which makes compiler implementation simplier), but it's not a physical restriction preventing multiple opCasts. The compiler could very well support the following: class Obj { int opCast(); float opCast(); } It just depends on how one makes the compiler parse source files. So, first we should discuss if there should be more than one opCast, and should there be implicit type conversion. How should it work in ambigious cases. Is that a reason why there is only one opCast? Or is it because implicit conversion makes code harder to read (it's less informative)?
Oct 01 2006
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Kristian wrote:
<snip>
 The documentation indeed states "Since functions cannot be overloaded 
 based on return value, there can be only one opCast per struct or 
 class.", but that's not the actual reason why there is only one opCast. 
 It may be a practical reason (which makes compiler implementation 
 simplier),

It's only simpler because the compiler wants to treat opCast just like any other identifier. But that is itself partly down to the fact that opCast is an identifier like any other. As such, you can call it as obj.opCast() just like any other function.
 but it's not a physical restriction preventing multiple 
 opCasts. The compiler could very well support the following:
 
 class Obj {
     int opCast();
     float opCast();
 }
 
 It just depends on how one makes the compiler parse source files.
 
 So, first we should discuss if there should be more than one opCast, and 
 should there be implicit type conversion. How should it work in 
 ambigious cases.

My impression was that it works only on casting to the exact return type of opCast.
 Is that a reason why there is only one opCast? Or is it 
 because implicit conversion makes code harder to read (it's less 
 informative)?

Please see my proposal http://tinyurl.com/p2pn4 It's very similar to your idea, but makes use of "cast", which is already a keyword, to be treated differently from ordinary function names. Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- C++ a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Oct 03 2006
next sibling parent J Duncan <jtd514 nospam.ameritech.net> writes:
Stewart Gordon wrote:
 Please see my proposal
 
 http://tinyurl.com/p2pn4
 
 It's very similar to your idea, but makes use of "cast", which is 
 already a keyword, to be treated differently from ordinary function names.
 
 Stewart.
 

I like that idea. Does anyone know what Walters long term plans are regarding the casting operator? It seems to me that a single cast operator is extremely lacking. So does anyone know if this is just temporary or does Walter not see a need for multiple casting operators?
Oct 03 2006
prev sibling parent Kristian <kjkilpi gmail.com> writes:
On Tue, 03 Oct 2006 21:39:15 +0300, Stewart Gordon <smjg_1998 yahoo.com>  
wrote:
 Kristian wrote:
 <snip>

 Please see my proposal

 http://tinyurl.com/p2pn4

 It's very similar to your idea, but makes use of "cast", which is  
 already a keyword, to be treated differently from ordinary function  
 names.

 Stewart.

If there will be multiple cast functions some day, I think the syntax "T cast() {...}" would be very nice. As you said, it makes a distinction from ordinary functions (and operator functions) by its name, which is a reserved word. (Of course, assuming that D will never have an ability to overload functions by their return values... ;) )
Oct 03 2006