D - [BUG?]: operator overloading
- Ivan Senji (44/44) Mar 22 2004 I asked this question before but here it is again:
- Manfred Nowak (19/21) Mar 23 2004 [...]
- Ivan Senji (5/26) Mar 24 2004 I dont't agree! A contains functions opShl(int) and opShl(char[]) but it
- Ilya Minkov (3/6) Mar 24 2004 I don't "agree" either, but so is the current spec. I checked it.
- Juan c (4/10) Mar 24 2004 Huh?! But A<
- Ivan Senji (15/29) Mar 24 2004 the
- Manfred Nowak (13/15) Mar 24 2004 [...]
- Ivan Senji (5/20) Mar 24 2004 My example doesn't involve coexistence of both operators! I
- Manfred Nowak (19/22) Mar 24 2004 [...]
- Ivan Senji (24/45) Mar 24 2004 OOPS! I didn't realize that(Thanks). But it isn't my intention to mimic
- J Anderson (5/54) Mar 24 2004 In this case the operation is comunitative, so m2 * v1 and v1 * m2 are
- Ivan Senji (9/11) Mar 25 2004 Ok but what if i for some reason neaded two vecto classes vectorRow and
- J Anderson (5/21) Mar 25 2004 Your right I was thinking scalar. Anyway you shouldn't be able m2 x v1
- Ivan Senji (4/7) Mar 25 2004 It is mathematicaly possible to do m2 * v1, but it isn't D-possible when
- Ivan Senji (9/11) Mar 25 2004 It is amthematicaly possible to do that, but it isn't D-possible when th...
- J Anderson (5/20) Mar 25 2004 I guess it's mythically ok if you use the vector (1x3 matrix) as a row
- Juan C (6/8) Mar 24 2004
- Ilya Minkov (17/21) Mar 24 2004 Like, you're not getting it. We are only talking of A<
- Manfred Nowak (20/26) Mar 25 2004 I think that this is the pioneering argument, provided that it is
- Ilya Minkov (18/49) Mar 25 2004 We can solve it like many similar questions. It is an error to define
- Carlos Santander B. (8/11) Mar 24 2004 But he isn't doing that. He defined A.opShl(int) so he can do A<<3. He a...
- Ivan Senji (25/39) Mar 24 2004 the
- Juan C (12/13) Mar 24 2004
- Ivan Senji (15/28) Mar 25 2004 from
- Ilya Minkov (16/21) Mar 24 2004 So it is. The purpose of _r overloads was to be able to add new
- Manfred Nowak (13/18) Mar 24 2004 [...]
- Ivan Senji (6/24) Mar 24 2004 Not true, example from spec:
- Manfred Nowak (6/11) Mar 24 2004 [...]
- Ilya Minkov (31/54) Mar 24 2004 Ok, you're right. But here's a real-life example:
- Ivan Senji (4/58) Mar 24 2004 general
- Ivan Senji (7/51) Mar 25 2004 Conclusion?: The way that operators work now should be changed because i...
- Kris (32/76) Mar 25 2004 There's an inter-related issue that exhibits this "short circuit" behavi...
- Ilya Minkov (9/23) Mar 25 2004 Yes, it is by design and C++ does the same IIRC. I think there was some
-
Kris
(3/5)
Mar 25 2004
My mistake ...
-
Carlos Santander B.
(27/27)
Mar 25 2004
"Ilya Minkov"
wrote in message - Ilya Minkov (3/4) Mar 26 2004 They should call superclass constructors.
- Walter (4/48) Aug 30 2004 You're right, it should work, and it does now. -Walter
I asked this question before but here it is again: For example i have this code class A { A opShl(int x) { printf("%d",x); return this; } A opShl(char[] x) { printf("%.*s",x); return this; } } class B { A opShl_r(A a) { //some code.. return a; } } int main(char[][] args) { A a; a << 4 << " " << 12 << "\n"; B b = new B(); a << b; getch(); return 1; } The line a<<b; causes this compilation error: E:\D language\learn_d\cout\cout.d(36): function opShl (int x) does not match argument types (B ) The compiler look for A.opShl(B) but it doesnt seam to look for B.opShl_r(A)?? If A.opShl(*) functions don't exist then the compiler finds and calls B.opShl_e(A), but then the first line a << 4 << " " << 12 << "\n"; doesn't work! So is this a bug? I hope it is and that it gets fixed!
Mar 22 2004
Ivan Senji wrote: [...]The compiler look for A.opShl(B) but it doesnt seam to look for B.opShl_r(A)??[...] From the spec: | a op b [...] | If a is a struct or class object reference that contains a member named | opfunc, the expression is rewritten as: | a.opfunc(b) Because your A contains `opShl' this rule holds and your B is not searched for `opShl_r'. According to the current specification it is not a bug to consider your code as erroneous. However, I consider the specification as either buggy itself, because it only defines a precendece, wheras it should disallow operands competing for operators at all, or the specification should be extended, so that only operands competing for operators using corresponding signature pairs are disallowed. Thoughts?
Mar 23 2004
"Manfred Nowak" <svv1999 hotmail.com> wrote in message news:c3rdt2$1d7g$1 digitaldaemon.com...Ivan Senji wrote: [...]I dont't agree! A contains functions opShl(int) and opShl(char[]) but it doesnt contain opShl(B) so it should still check if B contains opShl(A).The compiler look for A.opShl(B) but it doesnt seam to look for B.opShl_r(A)??[...] From the spec: | a op b [...] | If a is a struct or class object reference that contains a member named | opfunc, the expression is rewritten as: | a.opfunc(b) Because your A contains `opShl' this rule holds and your B is not searched for `opShl_r'.According to the current specification it is not a bug to consider your code as erroneous. However, I consider the specification as either buggy itself, because it only defines a precendece, wheras it should disallow operands competing for operators at all, or the specification should be extended, so that only operands competing for operators using corresponding signature pairs are disallowed. Thoughts?
Mar 24 2004
Ivan Senji schrieb:I dont't agree! A contains functions opShl(int) and opShl(char[]) but it doesnt contain opShl(B) so it should still check if B contains opShl(A).I don't "agree" either, but so is the current spec. I checked it. -eye
Mar 24 2004
Huh?! But A<<B is not the same as B<<A. I think you are trying to abuse the operator, and Walter doesn't like that. The << operator should _only_ be used to perform a left-shifting operation, which is not commutative. In article <c3sbqj$2s6n$2 digitaldaemon.com>, Ilya Minkov says...Ivan Senji schrieb:I dont't agree! A contains functions opShl(int) and opShl(char[]) but it doesnt contain opShl(B) so it should still check if B contains opShl(A).I don't "agree" either, but so is the current spec. I checked it. -eye
Mar 24 2004
"Juan c" <Juan_member pathlink.com> wrote in message news:c3sf1l$ib$1 digitaldaemon.com...Huh?! But A<<B is not the same as B<<A. I think you are trying to abusetheoperator, and Walter doesn't like that. The << operator should _only_ beused toperform a left-shifting operation, which is not commutative.A.opShl(B) should be same as B.opShl_r(A). I don't think it is abusing the operator if I am trying to use it to write simpler code! I (and probably a lot of other people coming from C++) see << and >> as stream operators before left-shifting. Someone may overload a static opCall operator to be able to use it like this A a = A(3,5); instead of A a = new A(3,5); Is this also abuse? I see it as a freedom to express your ideas in different ways.In article <c3sbqj$2s6n$2 digitaldaemon.com>, Ilya Minkov says...itIvan Senji schrieb:I dont't agree! A contains functions opShl(int) and opShl(char[]) butdoesnt contain opShl(B) so it should still check if B contains opShl(A).I don't "agree" either, but so is the current spec. I checked it. -eye
Mar 24 2004
Ivan Senji wrote: [...]A.opShl(B) should be same as B.opShl_r(A).[...] Should be. But this cannot be checked in the general case. Therefore the coexistence of both must be forbidden. I am unsure whether the compiler should check that for all possible competing classes/structs or it may suffice to check it only, when such classes/structs actually compete. [...]see << and >> as stream operators[...] Which is a strange and counter intuitive speciality made for {101}'s, not suitable for {500}'s. So long!
Mar 24 2004
"Manfred Nowak" <svv1999 hotmail.com> wrote in message news:c3sl87$c96$2 digitaldaemon.com...Ivan Senji wrote: [...]My example doesn't involve coexistence of both operators! I I only have B.opShl_r(A) and it is not called because A.opShl(int) and A.opShl(char[]) exist.A.opShl(B) should be same as B.opShl_r(A).[...] Should be. But this cannot be checked in the general case. Therefore the coexistence of both must be forbidden.I am unsure whether the compiler should check that for all possible competing classes/structs or it may suffice to check it only, when such classes/structs actually compete. [...]see << and >> as stream operators[...] Which is a strange and counter intuitive speciality made for {101}'s, not suitable for {500}'s. So long!
Mar 24 2004
Ivan Senji wrote: [...]My example doesn't involve coexistence of both operators! I I only have B.opShl_r(A) and it is not called because A.opShl(int) and A.opShl(char[]) exist.[...] I noticed that. And because your classes do not compete for the `<<' operator, there is good reason to allow B's `opShl_r' to be called. There is one more reason that especially your example should be allowed: your `opShl_r' returns the type of the left operand, which is the only requirement for the `<<' operator, which can be extracted from the spec. And as far as I can deduce from opover.c this requirement is not checked for by dmd. However, are you aware that your approach to mimic C++'s stream operator in D is illegal according to the spec? That is because the evaluation order for the operands of consecutive `<<'s is not defined. In the current version of dmd it may work, but in the next version or in another compiler may result in a syntax error. If you want such evaluated from left to right, you have to put it fully in brackets from left to right, which would totally obfuscate your purpose. So long!
Mar 24 2004
"Manfred Nowak" <svv1999 hotmail.com> wrote in message news:c3sqjj$tq9$1 digitaldaemon.com...Ivan Senji wrote: [...]OOPS! I didn't realize that(Thanks). But it isn't my intention to mimic C++'s streams, i am only experimenting :) I have another example (for this one no one can say it is abuse of operators): Lets say someone wrote a library that has a Matrix class. And I write a Vector class because i need it and i would like to use it together with Matrix Matrix class has "Matrix.opMul(Matrix)" and i wan't my Vector class to have Vector opMul(Matrix m) now i can use it like this: Matrix m1 = v1 * m2; but i can't use it like this: Matrix m1 = m2 * v1; Even if there existed opMul_r operator (i don't know why there isn't one) this still wouldn't work becouse of the Matrix.opMul(Matrix)! I like most every other feature of D very much (especially templates) but i just think there is something wrong in D's operator overloading! I don't think there is any solution to the problems like the one with Matrix and Vector. :( ?My example doesn't involve coexistence of both operators! I I only have B.opShl_r(A) and it is not called because A.opShl(int) and A.opShl(char[]) exist.[...] I noticed that. And because your classes do not compete for the `<<' operator, there is good reason to allow B's `opShl_r' to be called. There is one more reason that especially your example should be allowed: your `opShl_r' returns the type of the left operand, which is the only requirement for the `<<' operator, which can be extracted from the spec. And as far as I can deduce from opover.c this requirement is not checked for by dmd. However, are you aware that your approach to mimic C++'s stream operator in D is illegal according to the spec? That is because the evaluation order for the operands of consecutive `<<'s is not defined. In the current version of dmd it may work, but in the next version or in another compiler may result in a syntax error.If you want such evaluated from left to right, you have to put it fully in brackets from left to right, which would totally obfuscate your purpose. So long!
Mar 24 2004
Ivan Senji wrote:"Manfred Nowak" <svv1999 hotmail.com> wrote in message news:c3sqjj$tq9$1 digitaldaemon.com...In this case the operation is comunitative, so m2 * v1 and v1 * m2 are the same thing. Check out dig for a good matrix class. -- -Anderson: http://badmama.com.au/~anderson/Ivan Senji wrote: [...]OOPS! I didn't realize that(Thanks). But it isn't my intention to mimic C++'s streams, i am only experimenting :) I have another example (for this one no one can say it is abuse of operators): Lets say someone wrote a library that has a Matrix class. And I write a Vector class because i need it and i would like to use it together with Matrix Matrix class has "Matrix.opMul(Matrix)" and i wan't my Vector class to have Vector opMul(Matrix m) now i can use it like this: Matrix m1 = v1 * m2; but i can't use it like this: Matrix m1 = m2 * v1; Even if there existed opMul_r operator (i don't know why there isn't one) this still wouldn't work becouse of the Matrix.opMul(Matrix)!My example doesn't involve coexistence of both operators! I I only have B.opShl_r(A) and it is not called because A.opShl(int) and A.opShl(char[]) exist.[...] I noticed that. And because your classes do not compete for the `<<' operator, there is good reason to allow B's `opShl_r' to be called. There is one more reason that especially your example should be allowed: your `opShl_r' returns the type of the left operand, which is the only requirement for the `<<' operator, which can be extracted from the spec. And as far as I can deduce from opover.c this requirement is not checked for by dmd. However, are you aware that your approach to mimic C++'s stream operator in D is illegal according to the spec? That is because the evaluation order for the operands of consecutive `<<'s is not defined. In the current version of dmd it may work, but in the next version or in another compiler may result in a syntax error.
Mar 24 2004
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c3t0ha$17ta$1 digitaldaemon.com...In this case the operation is comunitative, so m2 * v1 and v1 * m2 are the same thing. Check out dig for a good matrix class.Ok but what if i for some reason neaded two vecto classes vectorRow and vectorColumn (and nobody can say that noone will ever need something like this) wtih these two vector classes m2*v1and v1*m2 isn't comutative. It isn't the same result if yout multiply a matrix with a vector row from left or from the right side.
Mar 25 2004
Ivan Senji wrote:"J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c3t0ha$17ta$1 digitaldaemon.com...Your right I was thinking scalar. Anyway you shouldn't be able m2 x v1 but if it's possible then it is not much trouble. -- -Anderson: http://badmama.com.au/~anderson/In this case the operation is comunitative, so m2 * v1 and v1 * m2 are the same thing. Check out dig for a good matrix class.Ok but what if i for some reason neaded two vecto classes vectorRow and vectorColumn (and nobody can say that noone will ever need something like this) wtih these two vector classes m2*v1and v1*m2 isn't comutative. It isn't the same result if yout multiply a matrix with a vector row from left or from the right side.
Mar 25 2004
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c3ueha$e35$1 digitaldaemon.com...It is mathematicaly possible to do m2 * v1, but it isn't D-possible when the left side class (int this case matrix) has a * operator defined.Your right I was thinking scalar. Anyway you shouldn't be able m2 x v1 but if it's possible then it is not much trouble.
Mar 25 2004
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c3ueha$e35$1 digitaldaemon.com...Your right I was thinking scalar. Anyway you shouldn't be able m2 x v1 but if it's possible then it is not much trouble.It is amthematicaly possible to do that, but it isn't D-possible when the left side class (in this case matrix) has any opMul defined! This is the problem: If class matrix doesn't have any operators opMul then vector is searched for opMul_r(matrix), but in the case of existance of matrix.opMul it doen't work.
Mar 25 2004
Ivan Senji wrote:"J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c3ueha$e35$1 digitaldaemon.com...I guess it's mythically ok if you use the vector (1x3 matrix) as a row for m x v and a column for v x m. -- -Anderson: http://badmama.com.au/~anderson/Your right I was thinking scalar. Anyway you shouldn't be able m2 x v1 but if it's possible then it is not much trouble.It is amthematicaly possible to do that, but it isn't D-possible when the left side class (in this case matrix) has any opMul defined! This is the problem: If class matrix doesn't have any operators opMul then vector is searched for opMul_r(matrix), but in the case of existance of matrix.opMul it doen't work.
Mar 25 2004
<snip>I (and probably a lot of other people coming from C++) see << and >> as stream operators before left-shifting.</snip> And it seems that's _why_ Walter doesn't want operators to be (ab)used for things like that. << is leftshift, >> is rightshift, and should _never_ have been used as stream operators in the first place. And even as stream operators; A<<B is not the same as B<<A !!
Mar 24 2004
Juan C schrieb:And it seems that's _why_ Walter doesn't want operators to be (ab)used for things like that. << is leftshift, >> is rightshift, and should _never_ have been used as stream operators in the first place.Perhaps. This is not the subject now.And even as stream operators; A<<B is not the same as B<<A !!Like, you're not getting it. We are only talking of A<<B - but insert something more sane in the place of <<, it can be % or ~ or whatever. This case can be resolved as A.Op(B) or B.Op_r(A). Notice that _r? It's to be able to expand the operator overloads without changing established class libraries. Now, the compiler refuses to consider the B.Op_r(A) resolution, because A.Op() is defined for some other type than B. This nonsensical situatition conforms to the specification. So i'd say the spec should be changed. It's not simply nonsensical, it's outright dangerous. Imagine A doesn't define .Op and there is a ton arbitrary code which defines .Op_r(A). Then the author of A decides to add a few .Op overloads to it. This breaks all other code which relies on the definitions of .Op_r(A), even if there is *no* *direct* *conflict*, that is no definition of C.Op_r(A) corresponds to A.Op(C) simply because the author of A is not aware of C, but C is aware of and requieres/uses A. -eye
Mar 24 2004
Ilya Minkov wrote: [...]Imagine A doesn't define .Op and there is a ton arbitrary code which defines .Op_r(A). Then the author of A decides to add a few .Op overloads to it. This breaks all other code which relies on the definitions of .Op_r(A), even if there is *no* *direct* *conflict*, that is no definition of C.Op_r(A) corresponds to A.Op(C) simply because the author of A is not aware of C, but C is aware of and requieres/uses A.I think that this is the pioneering argument, provided that it is posssible to code .Op_r by having access only to the public parts of A. Now to the next steps: 1) should the compiler check for competing overloads that may coincide, but actualyy do not; or should this checking only be done, when an overload is actually established; or should this being laid into the hands of the implementor of the compiler. 2) especially in the not overloaded case of `<<' it is defined, that the type of the result must be the type of the left operand. Should the compiler check the overloading functions for this requirement? Note: I think the latter has to do with the term `abuse', that sometimes drop into the discussions here. This reminds me of the french quotation marks "<<" and ">>". Would it be abuse, if someone would overload the shift operators in such a way, that they can be used as quotation marks? Moreover, in france quotations are made like "<< quoted text >>", whereas in germany the quotations are made ">> quoted text <<", if this quotation marks are used at all. So long!
Mar 25 2004
Manfred Nowak schrieb:Ilya Minkov wrote: [...]We can solve it like many similar questions. It is an error to define ambiguous overloads. It is a quality of implementation issue, if and under what circumstances the compiler can actually detect such an error. I would think that a simple compiler may provide the direct .op overload a precedence, while an advanced compiler may, when compiling a class which contains B.op_r(A), check that there is no match for A.op(B) and indicate an error if there is, and vice versa. I think i have to think over it a bit, since D allows covariant arguments, as opposed to C++ where they are invariant.Imagine A doesn't define .Op and there is a ton arbitrary code which defines .Op_r(A). Then the author of A decides to add a few .Op overloads to it. This breaks all other code which relies on the definitions of .Op_r(A), even if there is *no* *direct* *conflict*, that is no definition of C.Op_r(A) corresponds to A.Op(C) simply because the author of A is not aware of C, but C is aware of and requieres/uses A.I think that this is the pioneering argument, provided that it is posssible to code .Op_r by having access only to the public parts of A. Now to the next steps: 1) should the compiler check for competing overloads that may coincide, but actualyy do not; or should this checking only be done, when an overload is actually established; or should this being laid into the hands of the implementor of the compiler.2) especially in the not overloaded case of `<<' it is defined, that the type of the result must be the type of the left operand. Should the compiler check the overloading functions for this requirement?Hard to tell. I think rather not, as it currently is.Note: I think the latter has to do with the term `abuse', that sometimes drop into the discussions here. This reminds me of the french quotation marks "<<" and ">>". Would it be abuse, if someone would overload the shift operators in such a way, that they can be used as quotation marks? Moreover, in france quotations are made like "<< quoted text >>", whereas in germany the quotations are made ">> quoted text <<", if this quotation marks are used at all.Not much i could say here. Numeric operators were foreseen for numeric stuff, other operators were foreseen for their corresponding meanings. And while sprinkled abuse in general code may be very misleading, there is e.g. a C++ library which defines parsers in an elegant manner by using up an operator abuse. The way it is done there, the abuse is obvious and thus doesn't lead to problems. -eye
Mar 25 2004
In article <c3sf1l$ib$1 digitaldaemon.com>, Juan c says...Huh?! But A<<B is not the same as B<<A. I think you are trying to abuse the operator, and Walter doesn't like that. The << operator should _only_ be used to perform a left-shifting operation, which is not commutative.But he isn't doing that. He defined A.opShl(int) so he can do A<<3. He also wants to do A<<B, so he defined B.opShl_r(A), which should work, but doesn't. Yes, maybe he is abusing the operator, but that's his problem. Or maybe not: what if B is BigInteger? Then he wouldn't be abusing. One way or another, he's in all his rights to do things like this. ------------------- Carlos Santander B.
Mar 24 2004
"Juan c" <Juan_member pathlink.com> wrote in message news:c3sf1l$ib$1 digitaldaemon.com...Huh?! But A<<B is not the same as B<<A. I think you are trying to abusetheoperator, and Walter doesn't like that. The << operator should _only_ beused toperform a left-shifting operation, which is not commutative.I was wondering... what is the definition of abuse of operator? This code can be written in D, is this abuse? class ABC { static int opMul(char[] x){return 1;} static ABC opDiv(char[] x){return new ABC();} } ABC * "hello"; ABC abc = ABC / "hello again"; Is this code abuse? I think that there can't even be a definition of operator abuse because todays language features allow us to write things like the above. In the code above * and / obviously dont have the meaning of multiplication and division, but i like that we have the freedom to write something like that. Maybe the above code could have meaning to someone in some situation. It doesn't make sence that the language lets us write things like the above, but makes it impossible to use operators in some very common situations!In article <c3sbqj$2s6n$2 digitaldaemon.com>, Ilya Minkov says...itIvan Senji schrieb:I dont't agree! A contains functions opShl(int) and opShl(char[]) butdoesnt contain opShl(B) so it should still check if B contains opShl(A).I don't "agree" either, but so is the current spec. I checked it. -eye
Mar 24 2004
<snip>I was wondering... what is the definition of abuse of operator?</snip> It can't be defined, because not everyone would agree with any particular definition, or even whether or not such a concept is valid. I could say, "any implementation of an operator that differs substantially from its normal mathematical meaning". But that can be viewed as vague and maybe only half the people in this group would agree that that's abuse anyway. Many, like you perhaps, would argue that any operator can be used for any purpose. <analogy> Even though my SUV _allows_ me to drive anywhere, I am still obliged to follow the roads, so that other drivers can _reasonably predict_ what I'm likely to do. </analogy>
Mar 24 2004
"Juan C" <Juan_member pathlink.com> wrote in message news:c3t04c$17d8$1 digitaldaemon.com...<snip>fromI was wondering... what is the definition of abuse of operator?</snip> It can't be defined, because not everyone would agree with any particular definition, or even whether or not such a concept is valid. I could say, "any implementation of an operator that differs substantiallyits normal mathematical meaning". But that can be viewed as vague andmaybe onlyhalf the people in this group would agree that that's abuse anyway. Many,likeyou perhaps, would argue that any operator can be used for any purpose. <analogy> Even though my SUV _allows_ me to drive anywhere, I am still obliged tofollowthe roads, so that other drivers can _reasonably predict_ what I'm likelyto do.</analogy>Your car allows you to drive anywhere but the comunity doesn't, you can be punished. Same with the operators.If i write a library and the users think i am abusing operators nobody will use the library, and this will be my punishment! But we live in a free world so it shouldn't be made impossible to write inovative code wich in some context maybe makes sence.
Mar 25 2004
Manfred Nowak schrieb:However, I consider the specification as either buggy itself, because it only defines a precendece, wheras it should disallow operands competing for operators at all, or the specification should be extended, so that only operands competing for operators using corresponding signature pairs are disallowed.So it is. The purpose of _r overloads was to be able to add new overloads in newly written classes to the already exisiting infrastructure. With a current limitation, it does not fulfill this purpose. Consider that, e.g. class A is in the library, and B is user-written. A defines some operators for built-in and library types. Now this operator also should be made work with user types. The only sensible way to accomplish this is that if an overload search in A failed (that is, there possibly is an operator overload, but it doesn't match) a reversed overload has to be searched in B. Walter: was it a conscious decision to disallow that _r overloads be ignored in B if A defines some direct overload of this operator? The way it is now it's utterly useless and you could just as well remove all _r overloads! -eye
Mar 24 2004
Ilya Minkov wrote: [...]The purpose of _r overloads was to be able to add new overloads in newly written classes to the already exisiting infrastructure.[...] Do you have a reference for this? I ask, because I do not believe, that classes in any infrastructure are not allowed to have other types than classes/structs on the left side of a non commutative operator. [...]but it doesn't match) a reversed overload has to be searched in B.I do not believe that it is possible to code such overloads in the general case you established as an example. How can you assure, that it would suffice to have access to the public parts of class/struct A? [...]you could just as well remove all _r overloads!A stated above `B.opfunc_r(int)' may still make sense. So long!
Mar 24 2004
"Manfred Nowak" <svv1999 hotmail.com> wrote in message news:c3sl7u$bjt$1 digitaldaemon.com...Ilya Minkov wrote: [...]Not true, example from spec: class B { int opDiv_r(int i); } B b; 1 / b; // equivalent to b.opDiv_r(1)The purpose of _r overloads was to be able to add new overloads in newly written classes to the already exisiting infrastructure.[...] Do you have a reference for this? I ask, because I do not believe, that classes in any infrastructure are not allowed to have other types than classes/structs on the left side of a non commutative operator.[...]but it doesn't match) a reversed overload has to be searched in B.I do not believe that it is possible to code such overloads in the general case you established as an example. How can you assure, that it would suffice to have access to the public parts of class/struct A? [...]you could just as well remove all _r overloads!A stated above `B.opfunc_r(int)' may still make sense. So long!
Mar 24 2004
Ivan Senji wrote: [...]Not true, example from spec: class B { int opDiv_r(int i); } B b; 1 / b; // equivalent to b.opDiv_r(1)[...] Thanks for this confirmation from the spec for my suspicion. So long!
Mar 24 2004
Manfred Nowak schrieb:Ilya Minkov wrote: [...]Ok, you're right. But here's a real-life example: A widespread library defines numerical class A. For it, operators to divide it by an integer a float, and so on. are defined. Then you go ahead and write a Fixpoint struct. You want that you can divide A by your fixpoint just as by integer or a float. And you don't want to change A because you don't own it, and because you don't want A to be dependant on your fixpoint. So you define Fixpoint.opDiv_r(A). But hey, in current spec it DOES NOT WORK because A.opDiv(int) or some other unrelated stuff is defined!!! Now, one could consider not to define opDiv in A at all. But in the examples like above it simply doesn't come into consideration, because there is no other way to make it work with D's built in types!!! This is hardly acceptable. And while there is a workaround for classes by using interfaces, for structs it is a real dead end.The purpose of _r overloads was to be able to add new overloads in newly written classes to the already exisiting infrastructure.[...] Do you have a reference for this? I ask, because I do not believe, that classes in any infrastructure are not allowed to have other types than classes/structs on the left side of a non commutative operator.[...]I cannot, but imagine you are writing a library. You want that people can write extensions to your library. So you make sure they can - by making something public, or by providing a constructor. Of course it is only for cases which are foreseen. In principle, this situation is analogous to that of freestanding operators in C++, just that we don't have "friend", which wouldn't help here either.but it doesn't match) a reversed overload has to be searched in B.I do not believe that it is possible to code such overloads in the general case you established as an example. How can you assure, that it would suffice to have access to the public parts of class/struct A?Ok. i exaggerated. But the usefulness diminishes to almost zero. There was a discussion on freestanding operators. Everyone wanted them. Just that they don't live well with D's module system. Walter was strongly against. I had suggested that what they requiere, namely extensibility, can be achieved also with reverse overloads. Now i see that this doesn't work in the current spec. So, the discussion must be unrolled again, either freestanding operators, or reverse overloads which don't fail when non-conflicting direct overloads are defined. -eyeyou could just as well remove all _r overloads!A stated above `B.opfunc_r(int)' may still make sense.
Mar 24 2004
"Ilya Minkov" <minkov cs.tum.edu> wrote in message news:c3t1i5$19pm$1 digitaldaemon.com...Manfred Nowak schrieb:generalIlya Minkov wrote: [...]Ok, you're right. But here's a real-life example: A widespread library defines numerical class A. For it, operators to divide it by an integer a float, and so on. are defined. Then you go ahead and write a Fixpoint struct. You want that you can divide A by your fixpoint just as by integer or a float. And you don't want to change A because you don't own it, and because you don't want A to be dependant on your fixpoint. So you define Fixpoint.opDiv_r(A). But hey, in current spec it DOES NOT WORK because A.opDiv(int) or some other unrelated stuff is defined!!! Now, one could consider not to define opDiv in A at all. But in the examples like above it simply doesn't come into consideration, because there is no other way to make it work with D's built in types!!! This is hardly acceptable. And while there is a workaround for classes by using interfaces, for structs it is a real dead end.The purpose of _r overloads was to be able to add new overloads in newly written classes to the already exisiting infrastructure.[...] Do you have a reference for this? I ask, because I do not believe, that classes in any infrastructure are not allowed to have other types than classes/structs on the left side of a non commutative operator.[...]but it doesn't match) a reversed overload has to be searched in B.I do not believe that it is possible to code such overloads in theAll I can say is: Agree complety!case you established as an example. How can you assure, that it would suffice to have access to the public parts of class/struct A?I cannot, but imagine you are writing a library. You want that people can write extensions to your library. So you make sure they can - by making something public, or by providing a constructor. Of course it is only for cases which are foreseen. In principle, this situation is analogous to that of freestanding operators in C++, just that we don't have "friend", which wouldn't help here either.Ok. i exaggerated. But the usefulness diminishes to almost zero. There was a discussion on freestanding operators. Everyone wanted them. Just that they don't live well with D's module system. Walter was strongly against. I had suggested that what they requiere, namely extensibility, can be achieved also with reverse overloads. Now i see that this doesn't work in the current spec. So, the discussion must be unrolled again, either freestanding operators, or reverse overloads which don't fail when non-conflicting direct overloads are defined. -eyeyou could just as well remove all _r overloads!A stated above `B.opfunc_r(int)' may still make sense.
Mar 24 2004
Conclusion?: The way that operators work now should be changed because it is dangerous. The D way is generaly a good solution but they still have a big problem with *_r operators! "Ivan Senji" <ivan.senji public.srce.hr> wrote in message news:c3mdn2$225h$1 digitaldaemon.com...I asked this question before but here it is again: For example i have this code class A { A opShl(int x) { printf("%d",x); return this; } A opShl(char[] x) { printf("%.*s",x); return this; } } class B { A opShl_r(A a) { //some code.. return a; } } int main(char[][] args) { A a; a << 4 << " " << 12 << "\n"; B b = new B(); a << b; getch(); return 1; } The line a<<b; causes this compilation error: E:\D language\learn_d\cout\cout.d(36): function opShl (int x) does notmatchargument types (B ) The compiler look for A.opShl(B) but it doesnt seam to look for B.opShl_r(A)?? If A.opShl(*) functions don't exist then the compiler finds and calls B.opShl_e(A), but then the first line a << 4 << " " << 12 << "\n"; doesn't work! So is this a bug? I hope it is and that it gets fixed!
Mar 25 2004
There's an inter-related issue that exhibits this "short circuit" behavior: *any* set of methods with the same basic name (foo, get, put, opShl ...) do the same thing. For example, if I have two classes: class A { void foo(int x){} void foo(char[] x){} void foo(real x){} } class B : A { void foo (ubyte x){} } void test() { B b = new B(); b.foo ("test"); } The b.foo("test") generates a similar compile error ("function foo (ubyte x) does not match argument types (char[4])"). Apparently, once the basic name is found within a given class, the method resolver stops looking further down the inheritance chain for a better match. I don't like this, but it's per design (C++ does the same?). Walter has a way around this particular issue using alias: there's an additional small section in the online manual discussing it's use. However, it's not fully supported in release 0.81, and I don't know if it would resolve Ivan's opShl_r problem. I got around the same _r issue (for DSC) by applying an interface instead. - Kris "Ivan Senji" <ivan.senji public.srce.hr> wrote in message news:c3mdn2$225h$1 digitaldaemon.com...I asked this question before but here it is again: For example i have this code class A { A opShl(int x) { printf("%d",x); return this; } A opShl(char[] x) { printf("%.*s",x); return this; } } class B { A opShl_r(A a) { //some code.. return a; } } int main(char[][] args) { A a; a << 4 << " " << 12 << "\n"; B b = new B(); a << b; getch(); return 1; } The line a<<b; causes this compilation error: E:\D language\learn_d\cout\cout.d(36): function opShl (int x) does notmatchargument types (B ) The compiler look for A.opShl(B) but it doesnt seam to look for B.opShl_r(A)?? If A.opShl(*) functions don't exist then the compiler finds and calls B.opShl_e(A), but then the first line a << 4 << " " << 12 << "\n"; doesn't work! So is this a bug? I hope it is and that it gets fixed!
Mar 25 2004
Kris schrieb:There's an inter-related issue that exhibits this "short circuit" behavior: *any* set of methods with the same basic name (foo, get, put, opShl ...) do the same thing. For example, if I have two classes:--- 8< --- >8 ---The b.foo("test") generates a similar compile error ("function foo (ubyte x) does not match argument types (char[4])"). Apparently, once the basic name is found within a given class, the method resolver stops looking further down the inheritance chain for a better match. I don't like this, but it's per design (C++ does the same?).Yes, it is by design and C++ does the same IIRC. I think there was some smart reason to it. You have to import all other defs using alias.Walter has a way around this particular issue using alias: there's an additional small section in the online manual discussing it's use. However, it's not fully supported in release 0.81, and I don't know if it would resolve Ivan's opShl_r problem.No, it won't. Incompatible types. And this issue is no way related. Both behaviours are parts of specification.I got around the same _r issue (for DSC) by applying an interface instead.A pity it doesn't help for structs. If we had boxing it would, but then we would loose a lot of performance. -eye
Mar 25 2004
My mistake ... <g> "Ilya Minkov" <minkov cs.tum.edu> wrote in message news:c3vf6p$242t$1 digitaldaemon.com...No, it won't. Incompatible types. And this issue is no way related. Both behaviours are parts of specification.
Mar 25 2004
"Ilya Minkov" <minkov cs.tum.edu> wrote in message news:c3vf6p$242t$1 digitaldaemon.com | Kris schrieb: | || There's an inter-related issue that exhibits this "short circuit" behavior: || *any* set of methods with the same basic name (foo, get, put, opShl ...) do || the same thing. For example, if I have two classes: | | --- 8< --- >8 --- | || The b.foo("test") generates a similar compile error ("function foo (ubyte x) || does not match argument types (char[4])"). Apparently, once the basic name || is found within a given class, the method resolver stops looking further || down the inheritance chain for a better match. I don't like this, but it's || per design (C++ does the same?). | | Yes, it is by design and C++ does the same IIRC. I think there was some | smart reason to it. You have to import all other defs using alias. | However, the same can't be done for constructors. ----------------------- Carlos Santander Bernal
Mar 25 2004
Carlos Santander B. schrieb:However, the same can't be done for constructors.They should call superclass constructors. -eye
Mar 26 2004
You're right, it should work, and it does now. -Walter "Ivan Senji" <ivan.senji public.srce.hr> wrote in message news:c3mdn2$225h$1 digitaldaemon.com...I asked this question before but here it is again: For example i have this code class A { A opShl(int x) { printf("%d",x); return this; } A opShl(char[] x) { printf("%.*s",x); return this; } } class B { A opShl_r(A a) { //some code.. return a; } } int main(char[][] args) { A a; a << 4 << " " << 12 << "\n"; B b = new B(); a << b; getch(); return 1; } The line a<<b; causes this compilation error: E:\D language\learn_d\cout\cout.d(36): function opShl (int x) does notmatchargument types (B ) The compiler look for A.opShl(B) but it doesnt seam to look for B.opShl_r(A)?? If A.opShl(*) functions don't exist then the compiler finds and calls B.opShl_e(A), but then the first line a << 4 << " " << 12 << "\n"; doesn't work! So is this a bug? I hope it is and that it gets fixed!
Aug 30 2004