www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - opCast

reply Arcane Jill <Arcane_member pathlink.com> writes:
I mentioned this before. It seems such a simple thing, too.

I really think it's important that opCast() take a dummy parameter so that we
can overload on it, because you can't overload on the return type. Then, for
example, I would be able to do:

       class Int
       {
           int opCast(int dummy) { return toInt(); }
           long opCast(long dummy) { return toLong(); }
           double opCast(double dummy) { return toDouble(); }
       }

and so on. Without this, opCast is practically useless. This would be such an easy thing to add, would it not? It would certainly be of great benefit. Jill
Jun 08 2004
next sibling parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:ca3pj5$2cu$1 digitaldaemon.com...
 I mentioned this before. It seems such a simple thing, too.

And this time I will also agree!
 I really think it's important that opCast() take a dummy parameter so that

 can overload on it, because you can't overload on the return type. Then,

 example, I would be able to do:

       class Int
       {
           int opCast(int dummy) { return toInt(); }
           long opCast(long dummy) { return toLong(); }
           double opCast(double dummy) { return toDouble(); }
       }

and so on. Without this, opCast is practically useless. This would be such

 easy thing to add, would it not? It would certainly be of great benefit.

 Jill

Jun 08 2004
prev sibling next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 8 Jun 2004 07:24:21 +0000 (UTC), Arcane Jill wrote:

 I mentioned this before. It seems such a simple thing, too.
 
 I really think it's important that opCast() take a dummy parameter so that we
 can overload on it, because you can't overload on the return type. Then, for
 example, I would be able to do:
 
       class Int
       {
           int opCast(int dummy) { return toInt(); }
           long opCast(long dummy) { return toLong(); }
           double opCast(double dummy) { return toDouble(); }
       }

and so on. Without this, opCast is practically useless. This would be such an easy thing to add, would it not? It would certainly be of great benefit. Jill

Not to be able to overload opCast() does seem a bit pointless. So I agree with you AJ. BTW, its been a while since I've seen the rationale for not overloading based on return type. Can somebody refresh me on this point? -- Derek Melbourne, Australia 8/Jun/04 6:10:18 PM
Jun 08 2004
parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Derek Parnell" <derek psych.ward> wrote in message
news:ca3shk$85s$1 digitaldaemon.com...
 On Tue, 8 Jun 2004 07:24:21 +0000 (UTC), Arcane Jill wrote:

 I mentioned this before. It seems such a simple thing, too.

 I really think it's important that opCast() take a dummy parameter so


 can overload on it, because you can't overload on the return type. Then,


 example, I would be able to do:

       class Int
       {
           int opCast(int dummy) { return toInt(); }
           long opCast(long dummy) { return toLong(); }
           double opCast(double dummy) { return toDouble(); }
       }

and so on. Without this, opCast is practically useless. This would be


 easy thing to add, would it not? It would certainly be of great benefit.

 Jill

Not to be able to overload opCast() does seem a bit pointless. So I agree with you AJ. BTW, its been a while since I've seen the rationale for not overloading based on return type. Can somebody refresh me on this point?

int func(){return 3;} char[] func(){return "Hello";} func(); //which one to call?
 --
 Derek
 Melbourne, Australia
 8/Jun/04 6:10:18 PM

Jun 08 2004
parent reply Derek <derek psyc.ward> writes:
On Tue, 8 Jun 2004 10:58:30 +0200, Ivan Senji wrote:

 "Derek Parnell" <derek psych.ward> wrote in message
 news:ca3shk$85s$1 digitaldaemon.com...
 On Tue, 8 Jun 2004 07:24:21 +0000 (UTC), Arcane Jill wrote:

 I mentioned this before. It seems such a simple thing, too.

 I really think it's important that opCast() take a dummy parameter so


 can overload on it, because you can't overload on the return type. Then,


 example, I would be able to do:

       class Int
       {
           int opCast(int dummy) { return toInt(); }
           long opCast(long dummy) { return toLong(); }
           double opCast(double dummy) { return toDouble(); }
       }

and so on. Without this, opCast is practically useless. This would be


 easy thing to add, would it not? It would certainly be of great benefit.

 Jill

Not to be able to overload opCast() does seem a bit pointless. So I agree with you AJ. BTW, its been a while since I've seen the rationale for not overloading based on return type. Can somebody refresh me on this point?

int func(){return 3;} char[] func(){return "Hello";} func(); //which one to call?

Ah yes - the old "functions are assumed to return an int if the call is not explictly coded otherwise" trick. So how about, in the case of ambiguity (such as above), the compiler just tells you about it (error-abort) until you tell it explicitly... int a; a = func() or cast(int)func(); This resolution of ambiguity would only be needed where it actually existed, much like operator overloading now. -- Derek Melbourne, Australia
Jun 08 2004
parent Derek <derek psyc.ward> writes:
On Wed, 9 Jun 2004 07:51:09 +1000, Derek wrote:

 On Tue, 8 Jun 2004 10:58:30 +0200, Ivan Senji wrote:
 
 "Derek Parnell" <derek psych.ward> wrote in message
 news:ca3shk$85s$1 digitaldaemon.com...
 On Tue, 8 Jun 2004 07:24:21 +0000 (UTC), Arcane Jill wrote:

 I mentioned this before. It seems such a simple thing, too.

 I really think it's important that opCast() take a dummy parameter so


 can overload on it, because you can't overload on the return type. Then,


 example, I would be able to do:

       class Int
       {
           int opCast(int dummy) { return toInt(); }
           long opCast(long dummy) { return toLong(); }
           double opCast(double dummy) { return toDouble(); }
       }

and so on. Without this, opCast is practically useless. This would be


 easy thing to add, would it not? It would certainly be of great benefit.

 Jill

Not to be able to overload opCast() does seem a bit pointless. So I agree with you AJ. BTW, its been a while since I've seen the rationale for not overloading based on return type. Can somebody refresh me on this point?

int func(){return 3;} char[] func(){return "Hello";} func(); //which one to call?

Ah yes - the old "functions are assumed to return an int if the call is not explictly coded otherwise" trick. So how about, in the case of ambiguity (such as above), the compiler just tells you about it (error-abort) until you tell it explicitly... int a; a = func() or cast(int)func(); This resolution of ambiguity would only be needed where it actually existed, much like operator overloading now.

Ahhh! What was I thinking.. Okay, I've had breakfast and a shower now. Take Two: Maybe the compiler should just call the int func() as this is the default (used to automatically resolve ambiguity) and if the coder wishes to have the other called instead, she explictly nominates the return datatype. func(); // CAlls the int version. cast(char [])func(); // calls the other one. char[] a = func(); also calls the other one. -- Derek Melbourne, Australia
Jun 08 2004
prev sibling next sibling parent reply "Vathix" <vathixSpamFix dprogramming.com> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:ca3pj5$2cu$1 digitaldaemon.com...
 I mentioned this before. It seems such a simple thing, too.

 I really think it's important that opCast() take a dummy parameter so that

 can overload on it, because you can't overload on the return type. Then,

 example, I would be able to do:

       class Int
       {
           int opCast(int dummy) { return toInt(); }
           long opCast(long dummy) { return toLong(); }
           double opCast(double dummy) { return toDouble(); }
       }

and so on. Without this, opCast is practically useless. This would be such

 easy thing to add, would it not? It would certainly be of great benefit.

 Jill

I suggested using an out parameter instead of return value, like this: class Int { void opCast(out int result) { result = 3; } void opCast(out real result) { result = 3.0; } } So at least it doesn't look like a hack ;)
Jun 08 2004
next sibling parent reply James Widman <james jwidman.com> writes:
In article <ca4kdc$1k59$1 digitaldaemon.com>,
 "Vathix" <vathixSpamFix dprogramming.com> wrote:
 
 I suggested using an out parameter instead of return value, like this:
 
 class Int
 {
    void opCast(out int result) { result = 3; }
    void opCast(out real result) { result = 3.0; }
 }
 
 So at least it doesn't look like a hack ;)

...well, a lot of things in C++ don't look like hacks until you start reading the standard very carefully. To me the strangest part is that the function will behave as if it contained a return statement. So I guess it boils down to this: 1) is everybody ok with that lie? I don't think we should be, because it will inhibit people's ability to understand code. 2) how hard is it for compiler writers to handle this special case where there is a textually declared "void" return type but an implied cast-to return type and an implied "return" statement? My guess is that, although it may not seem hard, we can get into trouble if we start accepting features that mean the opposite of what is implied by the syntax. IMHO, a return type of "void" should mean "this function returns void". I vote for Jill's suggestion -- not that I actually have a vote. :-) One thing though, about Jill's example: since "dummy" is not used, need it be used in the opCast definition at all? On the other hand, would we be able to use "dummy" and expect that it contains the default initializer value for its type at the entry point of the function?
Jun 08 2004
next sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
What about:

    class Int
    {
        opCast(int)() { result = 3; }
        opCast(real)() { result = 3.0; }
    }

"James Widman" <james jwidman.com> wrote in message
news:james-D93ECD.13022008062004 digitalmars.com...
 In article <ca4kdc$1k59$1 digitaldaemon.com>,
  "Vathix" <vathixSpamFix dprogramming.com> wrote:
 I suggested using an out parameter instead of return value, like this:

 class Int
 {
    void opCast(out int result) { result = 3; }
    void opCast(out real result) { result = 3.0; }
 }

 So at least it doesn't look like a hack ;)

...well, a lot of things in C++ don't look like hacks until you start reading the standard very carefully. To me the strangest part is that the function will behave as if it contained a return statement. So I guess it boils down to this: 1) is everybody ok with that lie? I don't think we should be, because it will inhibit people's ability to understand code. 2) how hard is it for compiler writers to handle this special case where there is a textually declared "void" return type but an implied cast-to return type and an implied "return" statement? My guess is that, although it may not seem hard, we can get into trouble if we start accepting features that mean the opposite of what is implied by the syntax. IMHO, a return type of "void" should mean "this function returns void". I vote for Jill's suggestion -- not that I actually have a vote. :-) One thing though, about Jill's example: since "dummy" is not used, need it be used in the opCast definition at all? On the other hand, would we be able to use "dummy" and expect that it contains the default initializer value for its type at the entry point of the function?

Jun 08 2004
next sibling parent Regan Heath <regan netwin.co.nz> writes:
On Wed, 9 Jun 2004 07:50:15 +1000, Matthew <matthew.hat stlsoft.dot.org> 
wrote:
 What about:

     class Int
     {
         opCast(int)() { result = 3; }
         opCast(real)() { result = 3.0; }
     }

Nice, but I think class Int { int opCast() { return 3; } real opCast() { return 3.0; } } looks better. I realise you cannot overload on return type, but 'opCast' could be a special case where the compiler actually turns what I have above, into what Matthew has above above. Regan
 "James Widman" <james jwidman.com> wrote in message
 news:james-D93ECD.13022008062004 digitalmars.com...
 In article <ca4kdc$1k59$1 digitaldaemon.com>,
  "Vathix" <vathixSpamFix dprogramming.com> wrote:
 I suggested using an out parameter instead of return value, like this:

 class Int
 {
    void opCast(out int result) { result = 3; }
    void opCast(out real result) { result = 3.0; }
 }

 So at least it doesn't look like a hack ;)

...well, a lot of things in C++ don't look like hacks until you start reading the standard very carefully. To me the strangest part is that the function will behave as if it contained a return statement. So I guess it boils down to this: 1) is everybody ok with that lie? I don't think we should be, because it will inhibit people's ability to understand code. 2) how hard is it for compiler writers to handle this special case where there is a textually declared "void" return type but an implied cast-to return type and an implied "return" statement? My guess is that, although it may not seem hard, we can get into trouble if we start accepting features that mean the opposite of what is implied by the syntax. IMHO, a return type of "void" should mean "this function returns void". I vote for Jill's suggestion -- not that I actually have a vote. :-) One thing though, about Jill's example: since "dummy" is not used, need it be used in the opCast definition at all? On the other hand, would we be able to use "dummy" and expect that it contains the default initializer value for its type at the entry point of the function?


-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jun 08 2004
prev sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
Or

     class Int
     {
         int opCast() { result = 3; }
         real opCast() { result = 3.0; }
     }


"Matthew" <matthew.hat stlsoft.dot.org> wrote in message
news:ca5cel$2ug7$1 digitaldaemon.com...
 What about:

     class Int
     {
         opCast(int)() { result = 3; }
         opCast(real)() { result = 3.0; }
     }

 "James Widman" <james jwidman.com> wrote in message
 news:james-D93ECD.13022008062004 digitalmars.com...
 In article <ca4kdc$1k59$1 digitaldaemon.com>,
  "Vathix" <vathixSpamFix dprogramming.com> wrote:
 I suggested using an out parameter instead of return value, like this:

 class Int
 {
    void opCast(out int result) { result = 3; }
    void opCast(out real result) { result = 3.0; }
 }

 So at least it doesn't look like a hack ;)

...well, a lot of things in C++ don't look like hacks until you start reading the standard very carefully. To me the strangest part is that the function will behave as if it contained a return statement. So I guess it boils down to this: 1) is everybody ok with that lie? I don't think we should be, because it will inhibit people's ability to understand code. 2) how hard is it for compiler writers to handle this special case where there is a textually declared "void" return type but an implied cast-to return type and an implied "return" statement? My guess is that, although it may not seem hard, we can get into trouble if we start accepting features that mean the opposite of what is implied by the syntax. IMHO, a return type of "void" should mean "this function returns void". I vote for Jill's suggestion -- not that I actually have a vote. :-) One thing though, about Jill's example: since "dummy" is not used, need it be used in the opCast definition at all? On the other hand, would we be able to use "dummy" and expect that it contains the default initializer value for its type at the entry point of the function?


Jun 08 2004
parent Sean Kelly <sean f4.ca> writes:
In article <ca5e7o$7t$1 digitaldaemon.com>, Matthew says...
Or

     class Int
     {
         int opCast() { result = 3; }
         real opCast() { result = 3.0; }
     }

Which gets back to the old problem of overloading by return type. And while I'm sure Walter could make this a special case, special cases scare me :) This almost has me wanting to define member template function specializations for the purpose, except the syntax is kind of verbose: class Int { template opCast(T:int){ int opCast() { result = 3; } } template opCast(T:real){ real opCast() { result = 3.0; } } } Note that D doesn't recognize the above member templates as operator methods. Sean
Jun 08 2004
prev sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <james-D93ECD.13022008062004 digitalmars.com>, James Widman says...
In article <ca4kdc$1k59$1 digitaldaemon.com>,
 "Vathix" <vathixSpamFix dprogramming.com> wrote:
 
 I suggested using an out parameter instead of return value, like this:
 
 class Int
 {
    void opCast(out int result) { result = 3; }
    void opCast(out real result) { result = 3.0; }
 }
 
 So at least it doesn't look like a hack ;)


To me the strangest part is that the function will behave as if it 
contained a return statement.  

1) is everybody ok with that lie?  I don't think we should be, because 
it will inhibit people's ability to understand code.

No, this is fine. It's completely comprehensible. It's a void function which takes an out parameter. It reads fine. In fact, exactly the same trick is use to disambiguate all of the std.stream.Stream overloads. Check in out in the manual. There's... void read(out byte x) void read(out ubyte x) void read(out short x) void read(out ushort x) void read(out int x) ..and so on. If it's good enough for Phobos, it's good enough for me.
IMHO, a return type of "void" should mean "this function returns void". 

There's nothing wrong with a void function taking out parameters.
I vote for Jill's suggestion -- not that I actually have a vote. :-)

The syntax doesn't matter. All that matters is BEING ABLE TO DO IT AT ALL. I suggest we let Walter choose the syntax. I don't believe that any of us really care about the syntax all that much. Let's just be unequivocal about the fact that this is a desirable feature, whatever the syntax.
One thing though, about Jill's example: since "dummy" is not used, need 
it be used in the opCast definition at all? 

At present, it would be a compile error without it.
On the other hand, would we be able to use "dummy" and expect that it 
contains the default initializer value for its type at the entry point 
of the function?

I would imagine it would be initialized with .init, but who cares? Jill
Jun 08 2004
parent reply James Widman <james jwidman.com> writes:
In article <ca5fls$2oi$1 digitaldaemon.com>,
 Arcane Jill <Arcane_member pathlink.com> wrote:
1) is everybody ok with that lie?  I don't think we should be, because 
it will inhibit people's ability to understand code.

No, this is fine. It's completely comprehensible. It's a void function which takes an out parameter. It reads fine.

I think I'm ok with the concept of "out" parameters in general: you pass an argument to a function, and the function assigns something to it. So for: class A { void opCast(out int x) { x = 3; } } void f(A a) { int i; a.opCast(i); // OK; opCast will assign a value to "i". // XXX But as for this: i = cast(int)a; // opCast returns void...so for this to work there // must be a hidden variable (the "out" argument) // which will implicitly be used as if it were the // cast operator's return value. Should this work // in general for void functions that take a single // "out"? }
IMHO, a return type of "void" should mean "this function returns void". 

There's nothing wrong with a void function taking out parameters.

Agreed -- but because of the way the cast operator is used, it looks to me like the compiler would have to behave as if opCast had been declared as returning non-void -- that's the "lie" I referred to earlier. Or it could just be that I'm terribly confused. :-) Is there some relevant part of the spec that I should review?
 The syntax doesn't matter. All that matters is BEING ABLE TO DO IT AT ALL.I
 suggest we let Walter choose the syntax. I don't believe that any of us really
 care about the syntax all that much. 

Oh come on; if the syntax really didn't matter, we could just copy the way C++ does conversion operators. :-) ("Not that there's anything wrong with that...") I think the clean design of the syntax is one of the main reasons why D code is so much more readable than the equivalent C++ -- take templates, for example. Now, of course Walter's going to choose the syntax. But *everyone's* going to be stuck with it in the months and years to come (i.e., users, compiler writers, and language support tool-writers), so I think it pays to ask about these things.
 Let's just be unequivocal about the fact
 that this is a desirable feature, whatever the syntax.

It's definitely a desirable feature. :-) I'm sorry; I really don't want to be the nit-picker in the crowd. But in general, syntax issues really do matter. It affects the way language features will be used in the future, and it can affect the ease of implementation. Now so far, I think I like Matthew's suggestion best, but FWIW, here's my stab at it: class B { opCast(int) { return 0; } opCast(real) { return 0.0; } } Notes: 1) Any way you slice it, the addition of this feature implies an overload on the return type. Now in general, special cases should scare us, but since we're specifying the return type with /each invocation/, and that type (and the type of the cast-from object) is all we need to select the right overload, we should be scared less: void f(B b) { int i = cast(int)b; // it's pretty obvious which overload real r = cast(real)b; // we're selecting in both cases. 2) But since it is, after all, a special case, we should choose a syntax that shouts "I am a special case!" as loudly as possible. So "opCast" comes first in the declaration, then (parenthesized) return type, then function body. James
Jun 09 2004
next sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <james-F9B8BE.03385009062004 digitalmars.com>, James Widman says...
    i = cast(int)a;  // opCast returns void...so for this to work there 
                     // must be a hidden variable (the "out" argument)
                     // which will implicitly be used as if it were the
                     // cast operator's return value.  Should this work
                     // in general for void functions that take a single
                     // "out"?

It would be a compiler rewrite.
 int i = cast(int)a;

would have to be magically and invisibly transformed by the compiler into:
 int i = { int t; a.opCast(t); return t; };

Oh right. I see the problem. That won't compile, will it? Well then, back to my first suggestion I don't mind a dummy argument. No-one objects to the dummy argument in the C++ operator++(int). Maybe the only irritation here is that I named the dummy argument. Compare: 1) int opCast(int dummy); 2) int opCast(int); Now (2) looks nicer, I grant you. It just won't compile - though of course, Walter may be able to change that, for this special case only. But personally, I don't mind naming a dummy parameter. It doesn't bother me at all. It makes it clear that this IS a normal function, declared in the normal way - I just happen not to be using that particular parameter in the function body. Jill
Jun 09 2004
next sibling parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:ca6g4o$1igp$1 digitaldaemon.com...
 In article <james-F9B8BE.03385009062004 digitalmars.com>, James Widman says...
    i = cast(int)a;  // opCast returns void...so for this to work there
                     // must be a hidden variable (the "out" argument)
                     // which will implicitly be used as if it were the
                     // cast operator's return value.  Should this work
                     // in general for void functions that take a single
                     // "out"?

It would be a compiler rewrite.
 int i = cast(int)a;

would have to be magically and invisibly transformed by the compiler into:
 int i = { int t; a.opCast(t); return t; };

Oh right. I see the problem. That won't compile, will it? Well then, back to my first suggestion I don't mind a dummy argument. No-one objects to the dummy argument in the C++ operator++(int).

Only because there's no choice. It's a pretty horrible construction.
 Maybe the only irritation here is that I named the dummy argument. Compare:
 1)  int opCast(int dummy);
 2)  int opCast(int);

 Now (2) looks nicer, I grant you. It just won't compile - though of course,
 Walter may be able to change that, for this special case only. But personally,

 don't mind naming a dummy parameter. It doesn't bother me at all. It makes it
 clear that this IS a normal function, declared in the normal way - I just

 not to be using that particular parameter in the function body.

 Jill

Jun 09 2004
prev sibling parent reply James Widman <james jwidman.com> writes:
In article <ca6g4o$1igp$1 digitaldaemon.com>,
 Arcane Jill <Arcane_member pathlink.com> wrote:
 Maybe the only irritation here is that I named the dummy argument. Compare:
 1)  int opCast(int dummy);
 2)  int opCast(int);
 
 Now (2) looks nicer, I grant you. It just won't compile - though of course,
 Walter may be able to change that, for this special case only. But 
 personally, I
 don't mind naming a dummy parameter. It doesn't bother me at all. It makes it
 clear that this IS a normal function, 

Well, almost normal. There is one restriction though: a declaration like this is Right Out (TM): class A { real opCast(int x) { return 0.0; } } ...So the return type must match the parameter type. If we leave the return type out of the syntax, that's one less type equivalence check that the compiler would have to do. There are probably some other checks/diagnostics that can be avoided if we leave out the dummy name. (e.g., "name hides previous declaration" -- actually, that's probably the only one. Still, one less name lookup.) Less clutter for users, less clutter for compilers. If I missed something, then somebody whack me with a cluestick. :-) James
Jun 09 2004
parent Andy Friesen <andy ikagames.com> writes:
James Widman wrote:

 <snip>
 
 Well, almost normal. There is one restriction though: a declaration like 
 this is Right Out (TM): 
 
 class A
     {
     real opCast(int x) { return 0.0; }
     }
 
 ...So the return type must match the parameter type.  If we leave the 
 return type out of the syntax, that's one less type equivalence check 
 that the compiler would have to do.  There are probably some other 
 checks/diagnostics that can be avoided if we leave out the dummy name. 
 (e.g., "name hides previous declaration" -- actually, that's probably 
 the only one.  Still, one less name lookup.)  Less clutter for users, 
 less clutter for compilers. 
 
 If I missed something, then somebody whack me with a cluestick. :-)

It's not a big problem because normal type coersion rules can resolve this issue easily enough. If someone tries to do something freaky like char[] opCast(Object o), the types won't match, and the compiler will correctly complain. It'd be nice if the compiler enforced that the dummy argument matched the return type exactly, but only because it would make the error message nicer. -- andy
Jun 09 2004
prev sibling parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
"James Widman" <james jwidman.com> wrote in message
news:james-F9B8BE.03385009062004 digitalmars.com...
 In article <ca5fls$2oi$1 digitaldaemon.com>,
  Arcane Jill <Arcane_member pathlink.com> wrote:
1) is everybody ok with that lie?  I don't think we should be, because
it will inhibit people's ability to understand code.

No, this is fine. It's completely comprehensible. It's a void function which takes an out parameter. It reads fine.

I think I'm ok with the concept of "out" parameters in general: you pass an argument to a function, and the function assigns something to it. So for: class A { void opCast(out int x) { x = 3; } } void f(A a) { int i; a.opCast(i); // OK; opCast will assign a value to "i". // XXX But as for this: i = cast(int)a; // opCast returns void...so for this to work there // must be a hidden variable (the "out" argument) // which will implicitly be used as if it were the // cast operator's return value. Should this work // in general for void functions that take a single // "out"? }
IMHO, a return type of "void" should mean "this function returns void".

There's nothing wrong with a void function taking out parameters.

Agreed -- but because of the way the cast operator is used, it looks to me like the compiler would have to behave as if opCast had been declared as returning non-void -- that's the "lie" I referred to earlier. Or it could just be that I'm terribly confused. :-) Is there some relevant part of the spec that I should review?
 The syntax doesn't matter. All that matters is BEING ABLE TO DO IT AT ALL.I
 suggest we let Walter choose the syntax. I don't believe that any of us


 care about the syntax all that much.

Oh come on; if the syntax really didn't matter, we could just copy the way C++ does conversion operators. :-) ("Not that there's anything wrong with that...") I think the clean design of the syntax is one of the main reasons why D code is so much more readable than the equivalent C++ -- take templates, for example. Now, of course Walter's going to choose the syntax. But *everyone's* going to be stuck with it in the months and years to come (i.e., users, compiler writers, and language support tool-writers), so I think it pays to ask about these things.
 Let's just be unequivocal about the fact
 that this is a desirable feature, whatever the syntax.

It's definitely a desirable feature. :-) I'm sorry; I really don't want to be the nit-picker in the crowd. But in general, syntax issues really do matter. It affects the way language features will be used in the future, and it can affect the ease of implementation. Now so far, I think I like Matthew's suggestion best, but FWIW, here's my stab at it: class B { opCast(int) { return 0; } opCast(real) { return 0.0; } } Notes: 1) Any way you slice it, the addition of this feature implies an overload on the return type. Now in general, special cases should scare us, but since we're specifying the return type with /each invocation/, and that type (and the type of the cast-from object) is all we need to select the right overload, we should be scared less: void f(B b) { int i = cast(int)b; // it's pretty obvious which overload real r = cast(real)b; // we're selecting in both cases. 2) But since it is, after all, a special case, we should choose a syntax that shouts "I am a special case!" as loudly as possible. So "opCast" comes first in the declaration, then (parenthesized) return type, then function body.

Exactly correct. That's what I tried to achive with my suggestions. I'm happy with anything that marks this specialness; I certainly don't like the out param version for this reason
Jun 09 2004
prev sibling parent Sean Kelly <sean f4.ca> writes:
In article <ca4kdc$1k59$1 digitaldaemon.com>, Vathix says...
I suggested using an out parameter instead of return value, like this:

class Int
{
   void opCast(out int result) { result = 3; }
   void opCast(out real result) { result = 3.0; }
}

So at least it doesn't look like a hack ;)

Best suggestion I've seen so far :) Sean
Jun 08 2004
prev sibling parent reply "Vathix" <vathixSpamFix dprogramming.com> writes:
Just thought I'd mention this and see what comes of it. C# has keywords
"implicit" and "explicit" for overloading casts. D could get away with this
easier just by making a new function name like opImplicitCast or opCoerce
...
Jun 08 2004
next sibling parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <ca5kch$a5r$1 digitaldaemon.com>, Vathix says...
Just thought I'd mention this and see what comes of it. C# has keywords
"implicit" and "explicit" for overloading casts. D could get away with this
easier just by making a new function name like opImplicitCast or opCoerce
...

Cool. I mentioned that very thing only yesterday (digitalmars.D/3361). Obviously I agree with you. I don't care about the syntax though, only the feature. (Though I think it /has/ to be a constructor, not a regular function). Jill
Jun 08 2004
prev sibling parent Andy Friesen <andy ikagames.com> writes:
Vathix wrote:
 Just thought I'd mention this and see what comes of it. C# has keywords
 "implicit" and "explicit" for overloading casts. D could get away with this
 easier just by making a new function name like opImplicitCast or opCoerce
 ...

No no no no please no. When writing a smart pointer class in C++, writing both an operator bool() and an operator== can cause chaos when comparing with different smart pointers (when, for instance, interfacing with a library that has its own smart pointer) because C++ will sometimes prefer operator bool() over operator == when performing the comparison. Long story short, if you're not careful, the x==y comparison becomes equivalent to (x != 0) == y. Not Good. Implicit conversions are not a can of worms that should be opened. -- andy
Jun 08 2004