• 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
• Ilya Minkov (16/21) Mar 24 2004 So it is. The purpose of _r overloads was to be able to add new
• 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
• Walter (4/48) Aug 30 2004 You're right, it should work, and it does now. -Walter
"Ivan Senji" <ivan.senji public.srce.hr> writes:
```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
Manfred Nowak <svv1999 hotmail.com> writes:
```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
"Ivan Senji" <ivan.senji public.srce.hr> writes:
```"Manfred Nowak" <svv1999 hotmail.com> wrote in message
news:c3rdt2\$1d7g\$1 digitaldaemon.com...
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'.

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).

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
Ilya Minkov <minkov cs.tum.edu> writes:
```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
"Ivan Senji" <ivan.senji public.srce.hr> writes:
```"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 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.

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);
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...
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
Manfred Nowak <svv1999 hotmail.com> writes:
```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
"Ivan Senji" <ivan.senji public.srce.hr> writes:
```"Manfred Nowak" <svv1999 hotmail.com> wrote in message
news:c3sl87\$c96\$2 digitaldaemon.com...
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.

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 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> writes:
```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
"Ivan Senji" <ivan.senji public.srce.hr> writes:
```"Manfred Nowak" <svv1999 hotmail.com> wrote in message
news:c3sqjj\$tq9\$1 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.

[...]

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.

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

I don't think there is any solution to the problems like the one with Matrix
and Vector. :( ?

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...

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.

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)!

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.

--
```
Mar 24 2004
"Ivan Senji" <ivan.senji public.srce.hr> writes:
```"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...

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.

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
"Ivan Senji" <ivan.senji public.srce.hr> writes:
```"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 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.
```
Mar 25 2004
"Ivan Senji" <ivan.senji public.srce.hr> writes:
```"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...

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.

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.

--
```
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
Ilya Minkov <minkov cs.tum.edu> writes:
```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
Manfred Nowak <svv1999 hotmail.com> writes:
```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

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
Ilya Minkov <minkov cs.tum.edu> writes:
```Manfred Nowak schrieb:

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.

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.

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

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
Carlos Santander B. <Carlos_member pathlink.com> writes:
```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
"Ivan Senji" <ivan.senji public.srce.hr> writes:
```"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 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.

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...
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
```<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
"Ivan Senji" <ivan.senji public.srce.hr> writes:
```"Juan C" <Juan_member pathlink.com> wrote in message
news:c3t04c\$17d8\$1 digitaldaemon.com...
<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>

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
Ilya Minkov <minkov cs.tum.edu> writes:
```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
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

-eye
```
Mar 24 2004
Manfred Nowak <svv1999 hotmail.com> writes:
```Ilya Minkov wrote:

[...]
The purpose of _r overloads was to be able to add new
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

[...]
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" <ivan.senji public.srce.hr> writes:
```"Manfred Nowak" <svv1999 hotmail.com> wrote in message
news:c3sl7u\$bjt\$1 digitaldaemon.com...
Ilya Minkov wrote:

[...]
The purpose of _r overloads was to be able to add new
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.

Not true, example from spec:

class B { int opDiv_r(int i); }
B b;
1 / b;	// equivalent to b.opDiv_r(1)

[...]
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

[...]
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> writes:
```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
Ilya Minkov <minkov cs.tum.edu> writes:
```Manfred Nowak schrieb:

Ilya Minkov wrote:

[...]

The purpose of _r overloads was to be able to add new
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.

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.

[...]

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

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.

you could just as well remove all _r overloads!

A stated above `B.opfunc_r(int)' may still make sense.

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.

-eye
```
Mar 24 2004
"Ivan Senji" <ivan.senji public.srce.hr> writes:
```"Ilya Minkov" <minkov cs.tum.edu> wrote in message
news:c3t1i5\$19pm\$1 digitaldaemon.com...
Manfred Nowak schrieb:

Ilya Minkov wrote:

[...]

The purpose of _r overloads was to be able to add new
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.

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.

[...]

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

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.

you could just as well remove all _r overloads!

A stated above `B.opfunc_r(int)' may still make sense.

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.

-eye

All I can say is: Agree complety!
```
Mar 24 2004
"Ivan Senji" <ivan.senji public.srce.hr> writes:
```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 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 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

- 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 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 25 2004
Ilya Minkov <minkov cs.tum.edu> writes:
```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

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
"Carlos Santander B." <carlos8294 msn.com> writes:
```"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
Ilya Minkov <minkov cs.tum.edu> writes:
```Carlos Santander B. schrieb:

However, the same can't be done for constructors.

They should call superclass constructors.

-eye
```
Mar 26 2004
"Walter" <newshound digitalmars.com> writes:
```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 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!

```
Aug 30 2004