digitalmars.D.learn - Why is operator overloading like this in D?
- CloudiDust (20/20) Dec 09 2006 Greetings everybody, I am a novice in the D world (as well as one in a
- Daniel Keep (25/48) Dec 09 2006 Pretty much. For example, if you use cast(int)(some_float), then you
- CloudiDust (15/19) Dec 10 2006 Thank you very much Daniel!
- Frits van Bommel (9/20) Dec 10 2006 That's to allow calling it if you only have an Object reference. This is...
- Daniel Keep (8/36) Dec 11 2006 Because it's not part of the library. "dup" is a property of arrays,
- CloudiDust (3/3) Dec 13 2006 Thank you both Daniel & Frits.
Greetings everybody, I am a novice in the D world (as well as one in a newsgroup), come from the realm of C++. As I am so used to the operator overloading mechanism in C++, it's strange enough for me that the D way differs in a few aspects, as follows: 1. The cast operator can have only one overloaded version. Is it a way to force the programmers not to rely on type cast? 2. There is nothing like "opPreInc". In the reference, I got the point that "Since ++e is defined to be semantically equivalent to (e += 1), the expression ++e is rewritten as (e += 1) ...", so what if I only intend to overload the ++e, not the += operator, just like the way STL defined its input / forward iterators? 3. On the missing of "opAssign". Mr.Bright (I suppose :) stressed that we do not need to overload the assignment operator to do anything other than a bit copy. So if one struct contains pointers or references to others, we are hit. Maybe I am so immersed Could you give me some advice on how to "overcome" that? BTW: I wonder if the scoped objects are still references, as they are "newed"? Many thanks for your time, ~CloudiDust
Dec 09 2006
CloudiDust wrote:Greetings everybody, I am a novice in the D world (as well as one in a newsgroup), come from the realm of C++. As I am so used to the operator overloading mechanism in C++, it's strange enough for me that the D way differs in a few aspects, as follows:Welcome :)1. The cast operator can have only one overloaded version. Is it a way to force the programmers not to rely on type cast?Pretty much. For example, if you use cast(int)(some_float), then you have no control over what sort of cast: does it round (and if so, in what direction), or does it just truncate? The way to do this in D is to use a toType() function.2. There is nothing like "opPreInc". In the reference, I got the point that "Since ++e is defined to be semantically equivalent to (e += 1), the expression ++e is rewritten as (e += 1) ...", so what if I only intend to overload the ++e, not the += operator, just like the way STL defined its input / forward iterators?I think this has been done to prevent people from playing semantic silly-buggers with operators, like how C++ overloaded "+" to mean "concatenation" with strings. This way, ++ always means "+= 1". You have a reasonable expectation that operators do what you would expect them to. At the very least, "ptr.next" is self-explanatory, whilst "++ptr" isn't as much :33. On the missing of "opAssign". Mr.Bright (I suppose :) stressed that we do not need to overload the assignment operator to do anything other than a bit copy. So if one struct contains pointers or references to others, we are hit. Maybe I am so immersed Could you give me some advice on how to "overcome" that?Don't forget that because D is garbage collected, in the most cases, you don't need to do anything special if you have pointers. The GC will take care of things for you. If you really *do* need to copy the data a structure is pointing to, my suggestion would be to implement "dup" member functions. It's a little inconvenient, but it means that you can always count on "=" just doing a bit copy, and not something more. So "a = b" means "do a bit copy of b", and "a = b.dup" means "duplicate b in entirety". Plus, if you need to control how deep the copy does, you can use an argument.BTW: I wonder if the scoped objects are still references, as they are "newed"?Not really sure. I'll have to disassemble some code to check... :)Many thanks for your time, ~CloudiDustNo problem, hope this helped and enjoy your stay. -- Daniel
Dec 09 2006
Thank you very much Daniel! I wonder how to quote when posting? You wrote: (I quoted it manually :)If you really *do* need to copy the data a structure is pointing to, my suggestion would be to implement "dup" member functions. It's a little inconvenient, but it means that you can always count on "=" just doing a bit copy, and not something more.It seems that dup is not a member of Object according to the library reference, why? Is it because not everything can be duplicated? On the other hand, as there are many classes with which less or greater than comparisons (even equality tests) makes no sense, why opCmp becomes a "default"? Resulting in a requirement to make arguments of opCmp be of type Object when overloading? ( Maybe I'm just feeling unused to test the type of objects inside the functions. :) If not overloaded, opEquals does a bit comparison on everything, doesn't it? And from the reference, I get: "If a struct has no opCmp() function declared for it, attempting to compare two structs is an error." And what does the default opCmp do with classes? ~CloudiDust
Dec 10 2006
CloudiDust wrote:On the other hand, as there are many classes with which less or greater than comparisons (even equality tests) makes no sense, why opCmp becomes a "default"? Resulting in a requirement to make arguments of opCmp be of type Object when overloading?That's to allow calling it if you only have an Object reference. This is used in the implementation of associative arrays, and maybe some other places in the standard library.( Maybe I'm just feeling unused to test the type of objects inside the functions. :) If not overloaded, opEquals does a bit comparison on everything, doesn't it?In structs, yes. In classes, Object.opEquals compares addresses (object identity).And from the reference, I get: "If a struct has no opCmp() function declared for it, attempting to compare two structs is an error." And what does the default opCmp do with classes?Throw an exception. (It used to compare addresses, but that was bad because then the result can change between GC cycles if a moving collector is implemented)
Dec 10 2006
CloudiDust wrote:Thank you very much Daniel! I wonder how to quote when posting?I use a real news client, so I hit the "Reply" button :3You wrote: (I quoted it manually :)Because it's not part of the library. "dup" is a property of arrays, and sort of got extended to other things. You could name the method "copy" or "duplicate" or "frobnicate"--it's just a name, afterall. As long as you use it consistantly, it shouldn't be a problem.If you really *do* need to copy the data a structure is pointing to, my suggestion would be to implement "dup" member functions. It's a little inconvenient, but it means that you can always count on "=" just doing a bit copy, and not something more.It seems that dup is not a member of Object according to the library reference, why? Is it because not everything can be duplicated?On the other hand, as there are many classes with which less or greater than comparisons (even equality tests) makes no sense, why opCmp becomes a "default"? Resulting in a requirement to make arguments of opCmp be of type Object when overloading? ( Maybe I'm just feeling unused to test the type of objects inside the functions. :) If not overloaded, opEquals does a bit comparison on everything, doesn't it? And from the reference, I get: "If a struct has no opCmp() function declared for it, attempting to compare two structs is an error." And what does the default opCmp do with classes?I'll leave that to Frits, who has already answered it :)~CloudiDust
Dec 11 2006
Thank you both Daniel & Frits. So it means generally we should be careful using operator overloading and prefer "named" functions. :)
Dec 13 2006