www.digitalmars.com         C & C++   DMDScript  

D - Operator Overloading vote

reply Burton Radons <loth users.sourceforge.net> writes:
I've accidentally implemented operator overloading in my port.  It was 
kind of incidental to other work, so I thought "what the hell" and threw 
it in.  But this brings up the whole issue of syntax, and I think that 
should be voted on to specify the syntax on my side and to influence 
Walter when he decides to do this topic.

I'd like Apache-style voting to be used, where the voting is either -1, 
-0, 0, +0, or +1 for any option, which is a good bellweather of how 
people think about something.

First off, the naming scheme:

1) "add", "mul", "div", etc.  (my vote: +1)

     Vector mul (Vector b);
     Vector div (Vector b);

2) "op_add", "op_mul", "op_div", etc.  (my vote: +1)

     Vector op_sub (Vector b);
     Vector op_mod (Vector b);

3) "operator +".  (my vote: -1)  My vote is because I find this syntax 
confusing in C++, particularly with its wide expressiveness, and I 
admire any syntax which doesn't require a change to tools, as the above 
don't.

     Vector operator + (Vector b);

4) 'operator "+"'.  (my vote: -0)  For some reason I find this less 
visually disconcerting.

     Vector operator "*" (Vector b);

5) 'operator (a - b)' or 'operator (this - b)'.  (my vote: +0)  If I had 
to put in any new syntax I would prefer it to be this one.

     static Vector operator (a - b) (Vector a, Vector b);

Now, where overloaded operators are defined:

1) Operators are normal, possibly virtual methods in classes, normal 
nonvirtual methods in structs (My vote: +1).

     Vector add (Vector b);

2) Overloaded operators are always static methods with both left and 
right arguments defined (My vote: 0).

     static Vector add (Vector a, Vector b);

3) Overloaded operators are global functions, using both arguments (My 
vote: -1).

     Vector add (Vector a, Vector b);

4) Operator overloading shouldn't be put in (My vote: -1).

Now, reverse operator handling, where you want the right-side expression 
to handle the evaluation, such as with the form "int * Vector":

1) A second set of potential functions (My vote: +1).

2) Automatic reorganization of the expression.  This makes assumptions 
about what the operators do and can't handle "1 / Vector" (My vote: -1). 
  For example, "1-A" could become "-A+1".

Now for the operations covered.  Please be temperate with your votes - 
operations can be added later, but they can't be removed as easily.

1) a + b, a - b, a * b, a / b, a % b, -a, +a.  (my vote: +1)

2) a & b, a | b, a ^ b, ~a, !a.  (my vote: +1)

3) a++, a--, --a, ++a.  (my vote: 0)

4) a = b.  (my vote: 0)

5) a << b, a >> b, a >>> b.  (my vote: +1)

6) a += b, a -= b, a *= b, a %= b, etc.  (my vote: -1)

7) new, delete.  (my vote: -0)

8) a || b, a && b.  (my vote: -1)

9) explicit a >= b, a > b, a <= b, a < b.  (my vote: -1)

10) a [b].  (my vote: +1)

10a) a [b] = c.  (my vote: +0)

11) a [b .. c].  (my vote: +1)

12) &a, *a.  (my vote: -1)

13) a.b, a.b = c.  Retrieve and assign property.  (my vote: +1)  Note 
that this won't allow just anything in b.

13a) a . b, where b can be any type.  (my vote: -1)

14) a ? b : c.  (my vote: -1)

15) a === b, a !== b.  (my vote: 0)

16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my vote: 0) 
IMO this is an eq/cmp combination issue.

17) a in b.  (my vote: +1)

18) cast (b) a.  (my vote: -0)  I haven't had any good experiences with 
cast overloading in C++.

19) (a, b).  (my vote: -1)

And miscellaneous:

1) Operator overloading should be allowed on basic types as global 
functions.  (my vote: -1)

     int operator "a - b" (int a, int b);

2) Definition of new operators is allowed.  I'll ignore this one if it 
goes positive.  (my vote: -1)

     Vector operator (this dot b) (Vector b);

2a) Setting precedence of new operators is allowed.  I'll ignore this 
one if it goes positive.  (my vote: -1)

     operator (a dot b) above (a >= b) below (a * b);

I think that's about it.
Aug 08 2002
next sibling parent reply "Walter" <walter digitalmars.com> writes:
In general, I am leaning towards using simple names like add, mul, sub, etc.
Reverse operations should be addr, mulr, subr, etc. Overloading should be
restricted to arithmetic operators, and no assignment operators.

"Burton Radons" <loth users.sourceforge.net> wrote in message
news:3D5278B0.1000508 users.sourceforge.net...
 I've accidentally implemented operator overloading in my port.  It was
 kind of incidental to other work, so I thought "what the hell" and threw
 it in.  But this brings up the whole issue of syntax, and I think that
 should be voted on to specify the syntax on my side and to influence
 Walter when he decides to do this topic.

 I'd like Apache-style voting to be used, where the voting is either -1,
 -0, 0, +0, or +1 for any option, which is a good bellweather of how
 people think about something.

 First off, the naming scheme:

 1) "add", "mul", "div", etc.  (my vote: +1)

      Vector mul (Vector b);
      Vector div (Vector b);

 2) "op_add", "op_mul", "op_div", etc.  (my vote: +1)

      Vector op_sub (Vector b);
      Vector op_mod (Vector b);

 3) "operator +".  (my vote: -1)  My vote is because I find this syntax
 confusing in C++, particularly with its wide expressiveness, and I
 admire any syntax which doesn't require a change to tools, as the above
 don't.

      Vector operator + (Vector b);

 4) 'operator "+"'.  (my vote: -0)  For some reason I find this less
 visually disconcerting.

      Vector operator "*" (Vector b);

 5) 'operator (a - b)' or 'operator (this - b)'.  (my vote: +0)  If I had
 to put in any new syntax I would prefer it to be this one.

      static Vector operator (a - b) (Vector a, Vector b);

 Now, where overloaded operators are defined:

 1) Operators are normal, possibly virtual methods in classes, normal
 nonvirtual methods in structs (My vote: +1).

      Vector add (Vector b);

 2) Overloaded operators are always static methods with both left and
 right arguments defined (My vote: 0).

      static Vector add (Vector a, Vector b);

 3) Overloaded operators are global functions, using both arguments (My
 vote: -1).

      Vector add (Vector a, Vector b);

 4) Operator overloading shouldn't be put in (My vote: -1).

 Now, reverse operator handling, where you want the right-side expression
 to handle the evaluation, such as with the form "int * Vector":

 1) A second set of potential functions (My vote: +1).

 2) Automatic reorganization of the expression.  This makes assumptions
 about what the operators do and can't handle "1 / Vector" (My vote: -1).
   For example, "1-A" could become "-A+1".

 Now for the operations covered.  Please be temperate with your votes -
 operations can be added later, but they can't be removed as easily.

 1) a + b, a - b, a * b, a / b, a % b, -a, +a.  (my vote: +1)

 2) a & b, a | b, a ^ b, ~a, !a.  (my vote: +1)

 3) a++, a--, --a, ++a.  (my vote: 0)

 4) a = b.  (my vote: 0)

 5) a << b, a >> b, a >>> b.  (my vote: +1)

 6) a += b, a -= b, a *= b, a %= b, etc.  (my vote: -1)

 7) new, delete.  (my vote: -0)

 8) a || b, a && b.  (my vote: -1)

 9) explicit a >= b, a > b, a <= b, a < b.  (my vote: -1)

 10) a [b].  (my vote: +1)

 10a) a [b] = c.  (my vote: +0)

 11) a [b .. c].  (my vote: +1)

 12) &a, *a.  (my vote: -1)

 13) a.b, a.b = c.  Retrieve and assign property.  (my vote: +1)  Note
 that this won't allow just anything in b.

 13a) a . b, where b can be any type.  (my vote: -1)

 14) a ? b : c.  (my vote: -1)

 15) a === b, a !== b.  (my vote: 0)

 16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my vote: 0)
 IMO this is an eq/cmp combination issue.

 17) a in b.  (my vote: +1)

 18) cast (b) a.  (my vote: -0)  I haven't had any good experiences with
 cast overloading in C++.

 19) (a, b).  (my vote: -1)

 And miscellaneous:

 1) Operator overloading should be allowed on basic types as global
 functions.  (my vote: -1)

      int operator "a - b" (int a, int b);

 2) Definition of new operators is allowed.  I'll ignore this one if it
 goes positive.  (my vote: -1)

      Vector operator (this dot b) (Vector b);

 2a) Setting precedence of new operators is allowed.  I'll ignore this
 one if it goes positive.  (my vote: -1)

      operator (a dot b) above (a >= b) below (a * b);

 I think that's about it.

Aug 08 2002
next sibling parent Mark Evans <Mark_member pathlink.com> writes:
We should ask C++ experts who write numerical libraries what kind of operator
behavior they dream about at night.  (Blitz++ people?)

C++ operators limit what characters/strings can be used to represent an operator
function.  I think those choices should be mine to make:  "+special+" should be
valid if I want it.

I also might ask whether some kind of multipass compilation in D would
facilitate more flexibility with operators.  It would be cool to define a
function and then turn it into an operator by adding certain opeartor-ish
attributes like "representative symbol string", "precedence level", and
"prefix/infix/postfix".  Let alone "associativity" and "commutivity."  Well,
sorry for giving you a headache Walter, we will like whatever you do.

Mark
Aug 08 2002
prev sibling next sibling parent reply Mark Evans <Mark_member pathlink.com> writes:
In numerical work one typically prefers classes that know how to hand off
pointers to array data, not classes which mandate private internal copies of the
data.

STL vectors mandate internal data and it stinks.  Something as harmless as A = B
invokes a full array copy behind your back.  STL vector is thus a poor choice
for serious numerical work.

I hope that D offers some alternatives here.  STL is quite a disappointment
because it almost got there with its iterator and smart pointer concepts.

Mark
Aug 08 2002
parent Mark Evans <Mark_member pathlink.com> writes:
(Although the rope class may be something like what is required...reference
counted and all that...M.)
Aug 09 2002
prev sibling parent reply "Roberto Mariottini" <rmariottini lycosmail.com> writes:
"Walter" <walter digitalmars.com> ha scritto nel messaggio
news:aiubuj$2dmc$2 digitaldaemon.com...
 In general, I am leaning towards using simple names like add, mul, sub,

 Reverse operations should be addr, mulr, subr, etc. Overloading should be
 restricted to arithmetic operators, and no assignment operators.

Months ago, in an earlier discussion, was advanced the proposal of using _identifiers_ as operators. The proposal was like: Vector mul (Vector a, Vector b) { ... } // one vector multiplication Vector vec (Vector a, Vector b) { ... } // the other ... Vector x = ...; Vector y = ...; Vector w = x :mul: y; Vector z = x :vec: y; Identifier-operators have all the same precedence and are all left-associative and non-commutative. I think this is an easy way to use infix notation for nearly everything, and should be added to D whether other operator overloading is available or not. Ciao.
Aug 09 2002
parent "Walter" <walter digitalmars.com> writes:
"Roberto Mariottini" <rmariottini lycosmail.com> wrote in message
news:aj03sh$1lar$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> ha scritto nel messaggio
 news:aiubuj$2dmc$2 digitaldaemon.com...
 In general, I am leaning towards using simple names like add, mul, sub,

 Reverse operations should be addr, mulr, subr, etc. Overloading should


 restricted to arithmetic operators, and no assignment operators.

Months ago, in an earlier discussion, was advanced the proposal of using _identifiers_ as operators. The proposal was like: Vector mul (Vector a, Vector b) { ... } // one vector multiplication Vector vec (Vector a, Vector b) { ... } // the other ... Vector x = ...; Vector y = ...; Vector w = x :mul: y; Vector z = x :vec: y; Identifier-operators have all the same precedence and are all left-associative and non-commutative. I think this is an easy way to use infix notation for nearly everything,

 should be added to D
 whether other operator overloading is available or not.

It's a good idea, it would be interesting to see how readable it looks in a non-trivial situation.
Aug 11 2002
prev sibling next sibling parent Pavel Minayev <evilone omen.ru> writes:
On Thu, 08 Aug 2002 06:57:04 -0700 Burton Radons <loth users.sourceforge.net> 
wrote:

 First off, the naming scheme:
 
 1) "add", "mul", "div", etc.  (my vote: +1)
 
      Vector mul (Vector b);
      Vector div (Vector b);

-1
 2) "op_add", "op_mul", "op_div", etc.  (my vote: +1)
 
      Vector op_sub (Vector b);
      Vector op_mod (Vector b);

-1
 3) "operator +".  (my vote: -1)  My vote is because I find this syntax 
 confusing in C++, particularly with its wide expressiveness, and I 
 admire any syntax which doesn't require a change to tools, as the above 
 don't.
 
      Vector operator + (Vector b);

+0
 4) 'operator "+"'.  (my vote: -0)  For some reason I find this less 
 visually disconcerting.
 
      Vector operator "*" (Vector b);

-0 By the way, what about putting the operator in brackets - (*) rather than "*". It just seems to look better that way (at least to me). That one would get +1.
 5) 'operator (a - b)' or 'operator (this - b)'.  (my vote: +0)  If I had 
 to put in any new syntax I would prefer it to be this one.
 
      static Vector operator (a - b) (Vector a, Vector b);

0
 Now, where overloaded operators are defined:
 
 1) Operators are normal, possibly virtual methods in classes, normal 
 nonvirtual methods in structs (My vote: +1).
 
      Vector add (Vector b);

-1
 2) Overloaded operators are always static methods with both left and 
 right arguments defined (My vote: 0).
 
      static Vector add (Vector a, Vector b);

+1
 3) Overloaded operators are global functions, using both arguments (My 
 vote: -1).
 
      Vector add (Vector a, Vector b);

-0
 4) Operator overloading shouldn't be put in (My vote: -1).

-1 !!!
 Now, reverse operator handling, where you want the right-side expression 
 to handle the evaluation, such as with the form "int * Vector":
 
 1) A second set of potential functions (My vote: +1).

+1
 2) Automatic reorganization of the expression.  This makes assumptions 
 about what the operators do and can't handle "1 / Vector" (My vote: -1). 
   For example, "1-A" could become "-A+1".

-1
 Now for the operations covered.  Please be temperate with your votes - 
 operations can be added later, but they can't be removed as easily.
 
 1) a + b, a - b, a * b, a / b, a % b, -a, +a.  (my vote: +1)

+1
 2) a & b, a | b, a ^ b, ~a, !a.  (my vote: +1)

+1
 3) a++, a--, --a, ++a.  (my vote: 0)

+1
 4) a = b.  (my vote: 0)

-0
 5) a << b, a >> b, a >>> b.  (my vote: +1)

+0
 6) a += b, a -= b, a *= b, a %= b, etc.  (my vote: -1)

-0
 7) new, delete.  (my vote: -0)

-1
 8) a || b, a && b.  (my vote: -1)

0
 9) explicit a >= b, a > b, a <= b, a < b.  (my vote: -1)

+1
 10) a [b].  (my vote: +1)

+1
 10a) a [b] = c.  (my vote: +0)

+1
 11) a [b .. c].  (my vote: +1)

+1
 12) &a, *a.  (my vote: -1)

-1
 13) a.b, a.b = c.  Retrieve and assign property.  (my vote: +1)  Note 
 that this won't allow just anything in b.

0
 13a) a . b, where b can be any type.  (my vote: -1)

-1
 14) a ? b : c.  (my vote: -1)

-1
 15) a === b, a !== b.  (my vote: 0)

0
 16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my vote: 0) 
 IMO this is an eq/cmp combination issue.

+1 (it might differ for different argument types: for example, <> is not just !eq() for fp-numbers).
 17) a in b.  (my vote: +1)

0
 18) cast (b) a.  (my vote: -0)  I haven't had any good experiences with 
 cast overloading in C++.

-1 (good for "variant" types but too weird behaviour).
 19) (a, b).  (my vote: -1)

-1
 And miscellaneous:
 
 1) Operator overloading should be allowed on basic types as global 
 functions.  (my vote: -1)
 
      int operator "a - b" (int a, int b);

+1 (nothing can be better than overloading operator + for ints in your friend's program! =)). Seriously speaking, sometimes you might want to override language defaults. For example, make it so that int / int produces double (rather than int).
 2) Definition of new operators is allowed.  I'll ignore this one if it 
 goes positive.  (my vote: -1)
 
      Vector operator (this dot b) (Vector b);

-1
 2a) Setting precedence of new operators is allowed.  I'll ignore this 
 one if it goes positive.  (my vote: -1)
 
      operator (a dot b) above (a >= b) below (a * b);

-1
Aug 08 2002
prev sibling next sibling parent Patrick Down <pat codemoon.com> writes:
Burton Radons <loth users.sourceforge.net> wrote in news:3D5278B0.1000508
 users.sourceforge.net:


 
 First off, the naming scheme:
 
 1) "add", "mul", "div", etc.  (my vote: +1)
 
      Vector mul (Vector b);
      Vector div (Vector b);

+1
 
 2) "op_add", "op_mul", "op_div", etc.  (my vote: +1)
 
      Vector op_sub (Vector b);
      Vector op_mod (Vector b);

+1
 
 3) "operator +".  (my vote: -1)  My vote is because I find this syntax 
 confusing in C++, particularly with its wide expressiveness, and I 
 admire any syntax which doesn't require a change to tools, as the above 
 don't.
 
      Vector operator + (Vector b);

-1
 
 4) 'operator "+"'.  (my vote: -0)  For some reason I find this less 
 visually disconcerting.
 
      Vector operator "*" (Vector b);

-0
 
 5) 'operator (a - b)' or 'operator (this - b)'.  (my vote: +0)  If I 

 to put in any new syntax I would prefer it to be this one.
 
      static Vector operator (a - b) (Vector a, Vector b);

+0
 
 Now, where overloaded operators are defined:
 
 1) Operators are normal, possibly virtual methods in classes, normal 
 nonvirtual methods in structs (My vote: +1).
 
      Vector add (Vector b);

+1
 
 2) Overloaded operators are always static methods with both left and 
 right arguments defined (My vote: 0).
 
      static Vector add (Vector a, Vector b);

+0
 
 3) Overloaded operators are global functions, using both arguments (My 
 vote: -1).
 
      Vector add (Vector a, Vector b);

-1
 
 4) Operator overloading shouldn't be put in (My vote: -1).

-0
 
 Now, reverse operator handling, where you want the right-side 

 to handle the evaluation, such as with the form "int * Vector":
 
 1) A second set of potential functions (My vote: +1).

+1
 
 2) Automatic reorganization of the expression.  This makes assumptions 
 about what the operators do and can't handle "1 / Vector" (My vote: -

   For example, "1-A" could become "-A+1".

-1
 
 Now for the operations covered.  Please be temperate with your votes - 
 operations can be added later, but they can't be removed as easily.
 
 1) a + b, a - b, a * b, a / b, a % b, -a, +a.  (my vote: +1)

+1 What about a ~ b
 
 2) a & b, a | b, a ^ b, ~a, !a.  (my vote: +1)

+1
 
 3) a++, a--, --a, ++a.  (my vote: 0)

+1
 
 4) a = b.  (my vote: 0)

-1
 
 5) a << b, a >> b, a >>> b.  (my vote: +1)

+1
 
 6) a += b, a -= b, a *= b, a %= b, etc.  (my vote: -1)

+0
 
 7) new, delete.  (my vote: -0)

+1
 
 8) a || b, a && b.  (my vote: -1)

-1
 
 9) explicit a >= b, a > b, a <= b, a < b.  (my vote: -1)

I like cmp as it is
 
 10) a [b].  (my vote: +1)

+1
 
 10a) a [b] = c.  (my vote: +0)

+1
 
 11) a [b .. c].  (my vote: +1)

+1
 
 12) &a, *a.  (my vote: -1)

-1
 
 13) a.b, a.b = c.  Retrieve and assign property.  (my vote: +1)  Note 
 that this won't allow just anything in b.

+1
 
 13a) a . b, where b can be any type.  (my vote: -1)

-1
 
 14) a ? b : c.  (my vote: -1)

-1
 
 15) a === b, a !== b.  (my vote: 0)

-1
 
 16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my vote: 0) 
 IMO this is an eq/cmp combination issue.

0
 
 17) a in b.  (my vote: +1)

+1
 
 18) cast (b) a.  (my vote: -0)  I haven't had any good experiences with 
 cast overloading in C++.

-1
 
 19) (a, b).  (my vote: -1)

-1
 
 And miscellaneous:
 
 1) Operator overloading should be allowed on basic types as global 
 functions.  (my vote: -1)
 
      int operator "a - b" (int a, int b);

0 Perhaps on typedefs.
 
 2) Definition of new operators is allowed.  I'll ignore this one if it 
 goes positive.  (my vote: -1)
 
      Vector operator (this dot b) (Vector b);

0 If it was implemented that x.func(y) could be expressed as (x func y) it might be cool. However I would set them all to be the same precedence.
 
 2a) Setting precedence of new operators is allowed.  I'll ignore this 
 one if it goes positive.  (my vote: -1)
 
      operator (a dot b) above (a >= b) below (a * b);

-1
 
 I think that's about it.

Aug 08 2002
prev sibling next sibling parent "anderson" <anderson firestar.com.au> writes:
"Burton Radons" <loth users.sourceforge.net> wrote in message
news:3D5278B0.1000508 users.sourceforge.net...
 I've accidentally implemented operator overloading in my port.  It was
 kind of incidental to other work, so I thought "what the hell" and threw
 it in.  But this brings up the whole issue of syntax, and I think that
 should be voted on to specify the syntax on my side and to influence
 Walter when he decides to do this topic.

 I'd like Apache-style voting to be used, where the voting is either -1,
 -0, 0, +0, or +1 for any option, which is a good bellweather of how
 people think about something.

 First off, the naming scheme:

 1) "add", "mul", "div", etc.  (my vote: +1)

      Vector mul (Vector b);
      Vector div (Vector b);

+1
 2) "op_add", "op_mul", "op_div", etc.  (my vote: +1)

      Vector op_sub (Vector b);
      Vector op_mod (Vector b);

0
 3) "operator +".  (my vote: -1)  My vote is because I find this syntax
 confusing in C++, particularly with its wide expressiveness, and I
 admire any syntax which doesn't require a change to tools, as the above
 don't.

      Vector operator + (Vector b);

0
 4) 'operator "+"'.  (my vote: -0)  For some reason I find this less
 visually disconcerting.

      Vector operator "*" (Vector b);

+1
 5) 'operator (a - b)' or 'operator (this - b)'.  (my vote: +0)  If I had
 to put in any new syntax I would prefer it to be this one.

      static Vector operator (a - b) (Vector a, Vector b);

 Now, where overloaded operators are defined:

+1
 1) Operators are normal, possibly virtual methods in classes, normal
 nonvirtual methods in structs (My vote: +1).

      Vector add (Vector b);

+1
 2) Overloaded operators are always static methods with both left and
 right arguments defined (My vote: 0).

      static Vector add (Vector a, Vector b);

-1 (not always)
 3) Overloaded operators are global functions, using both arguments (My
 vote: -1).

      Vector add (Vector a, Vector b);

-1
 4) Operator overloading shouldn't be put in (My vote: -1).

 Now, reverse operator handling, where you want the right-side expression
 to handle the evaluation, such as with the form "int * Vector":

 1) A second set of potential functions (My vote: +1).

+1
 2) Automatic reorganization of the expression.  This makes assumptions
 about what the operators do and can't handle "1 / Vector" (My vote: -1).
   For example, "1-A" could become "-A+1".

-1
 Now for the operations covered.  Please be temperate with your votes -
 operations can be added later, but they can't be removed as easily.

 1) a + b, a - b, a * b, a / b, a % b, -a, +a.  (my vote: +1)

+1
 2) a & b, a | b, a ^ b, ~a, !a.  (my vote: +1)

+1
 3) a++, a--, --a, ++a.  (my vote: 0)

+1
 4) a = b.  (my vote: 0)

+1
 5) a << b, a >> b, a >>> b.  (my vote: +1)

0
 6) a += b, a -= b, a *= b, a %= b, etc.  (my vote: -1)

 7) new, delete.  (my vote: -0)

-1
 8) a || b, a && b.  (my vote: -1)

+1
 9) explicit a >= b, a > b, a <= b, a < b.  (my vote: -1)

+1 (good for sorting ect...)
 10) a [b].  (my vote: +1)

+1
 10a) a [b] = c.  (my vote: +0)

0
 11) a [b .. c].  (my vote: +1)

+1
 12) &a, *a.  (my vote: -1)

-1
 13) a.b, a.b = c.  Retrieve and assign property.  (my vote: +1)  Note
 that this won't allow just anything in b.

0
 13a) a . b, where b can be any type.  (my vote: -1)

 14) a ? b : c.  (my vote: -1)

-1
 15) a === b, a !== b.  (my vote: 0)

0 (hummm)
 16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my vote: 0)
 IMO this is an eq/cmp combination issue.

0
 17) a in b.  (my vote: +1)

+1
 18) cast (b) a.  (my vote: -0)  I haven't had any good experiences with
 cast overloading in C++.

+1 (Conversion constructor?)
 19) (a, b).  (my vote: -1)

-1
 And miscellaneous:

 1) Operator overloading should be allowed on basic types as global
 functions.  (my vote: -1)

      int operator "a - b" (int a, int b);

-1
 2) Definition of new operators is allowed.  I'll ignore this one if it
 goes positive.  (my vote: -1)

      Vector operator (this dot b) (Vector b);

-1
 2a) Setting precedence of new operators is allowed.  I'll ignore this
 one if it goes positive.  (my vote: -1)

      operator (a dot b) above (a >= b) below (a * b);

0
 I think that's about it.

PS - This will probably be ignored, but I'd also like +,-,* type operators able to be specified as constructors. I'm not say that it should be the only way of specifying overloading because it's ineffecient. I'm just saying that it's conveniant and logical, because in many cases you normally end up creating a new object anyway. this mul (Vector a, Vector b); //I don't care about the syntax but it shouldn't be static
Aug 08 2002
prev sibling next sibling parent C.R.Chafer <blackmarlin nospam.asean-mail.com> writes:
[portions snipped to reduce length]

- Good ideas here is my votes and some comments

Burton Radons wrote:

 First off, the naming scheme:
 
 1) "add", "mul", "div", etc.  (my vote: +1)

+0
2) "op_add", "op_mul", "op_div", etc.  (my vote: +1)

0
3) "operator +".  (my vote: -1)

-0
 4) 'operator "+"'.  (my vote: -0)

0
 5) 'operator (a - b)' or 'operator (this - b)'.

+1 But what if you want to call it as a standard function? <added> 6) (added) 'sub operator (a-b)' or 'sub operator (this-b) static Vector sub operator (a - b) (Vector a, Vector b ); +1 </added>
 1) Operators are normal, possibly virtual methods in classes, normal
 nonvirtual methods in structs (My vote: +1).

+0
 2) Overloaded operators are always static methods with both left and
 right arguments defined (My vote: 0).

0
 3) Overloaded operators are global functions, using both arguments (My
 vote: -1).

-0
 4) Operator overloading shouldn't be put in (My vote: -1).

-1
 1) A second set of potential functions (My vote: +1).

+0
 2) Automatic reorganization of the expression.  This makes assumptions
 about what the operators do and can't handle "1 / Vector" (My vote: -1).

-0 (could be useful for error reporting, but a pain to implement)
 1) a + b, a - b, a * b, a / b, a % b, -a, +a.  (my vote: +1)

+1
 2) a & b, a | b, a ^ b, ~a, !a.  (my vote: +1)

+1
 3) a++, a--, --a, ++a.  (my vote: 0)

+0 (but mode (a-- or --a) would be a pain without type 5) or *6)* style operator defines)
 4) a = b.  (my vote: 0)

-0
 5) a << b, a >> b, a >>> b.  (my vote: +1)

+1
 6) a += b, a -= b, a *= b, a %= b, etc.  (my vote: -1)

-0 (could be useful - but probably better to leave seperate)
 7) new, delete.  (my vote: -0)

-1 (overloading new & delete is asking for trouble)
 8) a || b, a && b.  (my vote: -1)

+0
 9) explicit a >= b, a > b, a <= b, a < b.  (my vote: -1)

+0 (what about NaN in floats etc)
 10) a [b].  (my vote: +1)

-0
 10a) a [b] = c.  (my vote: +0)

-1
 11) a [b .. c].  (my vote: +1)

0
 12) &a, *a.  (my vote: -1)

-1
 13) a.b, a.b = c.  Retrieve and assign property.  (my vote: +1)  Note
 that this won't allow just anything in b.

0
 13a) a . b, where b can be any type.  (my vote: -1)

-0
 14) a ? b : c.  (my vote: -1)

0 (only possible for syntax types 5) & *6)*
 15) a === b, a !== b.  (my vote: 0)

-0 (reference compares should remain exactly that - only compare ptr)
 16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my vote: 0)
 IMO this is an eq/cmp combination issue.

+0 (again what about NaN in floats)
 17) a in b.  (my vote: +1)

+1
 18) cast (b) a.  (my vote: -0)  I haven't had any good experiences with
 cast overloading in C++.

+0 (there is two types of cast 1. override value (use one bit patten as another type) and 2. alter value (ie convert from float to int) - although type 1 should not be overloaded type 2 should - maybe D needs different syntax for each type of cast?)
 19) (a, b).  (my vote: -1)

-1
 And miscellaneous:
 
 1) Operator overloading should be allowed on basic types as global
 functions.  (my vote: -1)

0 (could be useful - but likely to be misused especially if overloading is global - would only recommend if there were no basic types)
 2) Definition of new operators is allowed.  I'll ignore this one if it
 goes positive.  (my vote: -1)

+1 (very useful but two issues 1. precidence (how to set - see below) & 2. syntax / semantic seperation - 2. may be solved by ie prefixing new operators with a special character ie. Vector dot operator (this #dot b ) ( Vector b ); or Vector dot operator (this #dot# b ) ( Vector b ); )
 2a) Setting precedence of new operators is allowed.  I'll ignore this
 one if it goes positive.  (my vote: -1)
 
      operator (a dot b) above (a >= b) below (a * b);

+1 needed for defining new operators (else set new ops at fixed precidence) (word "new" is important) C 2002/8/9
Aug 09 2002
prev sibling next sibling parent reply C.R.Chafer <blackmarlin nospam.asean-mail.com> writes:
For comments additional format (should be just as easy to parse - and the 
function name could be optional)

6) (added) 'sub operator (a-b)' or 'sub operator (this-b)

static Vector sub operator (a - b) (Vector a, Vector b );

+1

EBNF (elc) ->
`` assumes function name is optional

operatorOverloadFunction
:       [ "static" ] type [ Identifier ] "operator"
                "(" form ")" "(" [ arguments ] ")"
;

form
:       operator Identifier
|       Identifier operator Identifier
|       Identifier operator
;

C 2002/8/9
Aug 09 2002
parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
I'd be just fine with this:

Vector operator(Vector a - Vector b)
{
    return a.sub(b);
}

Vector operator(-Vector a)
{
    return a.negate();
}

operators only permitted at module scope.

I too would like to see

Vector operator(Vector a dot Vector b)
{
    return a.dot(b);
}

It should be easy enough to parse the declarations out separately from the
operator symbols.

Sean

"C.R.Chafer" <blackmarlin nospam.asean-mail.com> wrote in message
news:aj08qk$1qc3$1 digitaldaemon.com...
 For comments additional format (should be just as easy to parse - and the
 function name could be optional)

 6) (added) 'sub operator (a-b)' or 'sub operator (this-b)

 static Vector sub operator (a - b) (Vector a, Vector b );

 +1

 EBNF (elc) ->
 `` assumes function name is optional

 operatorOverloadFunction
 :       [ "static" ] type [ Identifier ] "operator"
                 "(" form ")" "(" [ arguments ] ")"
 ;

 form
 :       operator Identifier
 |       Identifier operator Identifier
 |       Identifier operator
 ;

 C 2002/8/9

Aug 09 2002
parent "Juan Carlos Arevalo Baeza" <jcab roningames.com> writes:
"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:aj0sgr$2fqb$1 digitaldaemon.com...

 I'd be just fine with this:

 Vector operator(Vector a - Vector b)
 Vector operator(-Vector a)

This is my favorite syntax, too. For clarity, and to ease parsing, I'd enforce parenthesis for each definition, like this: Vector operator((Vector a) - (Vector b)) Vector operator(-(Vector a)) Salutaciones, JCAB
Aug 13 2002
prev sibling next sibling parent "Sean L. Palmer" <seanpalmer earthlink.net> writes:
"Burton Radons" <loth users.sourceforge.net> wrote in message
news:3D5278B0.1000508 users.sourceforge.net...
 I've accidentally implemented operator overloading in my port.  It was
 kind of incidental to other work, so I thought "what the hell" and threw
 it in.  But this brings up the whole issue of syntax, and I think that
 should be voted on to specify the syntax on my side and to influence
 Walter when he decides to do this topic.

 I'd like Apache-style voting to be used, where the voting is either -1,
 -0, 0, +0, or +1 for any option, which is a good bellweather of how
 people think about something.

 First off, the naming scheme:

 1) "add", "mul", "div", etc.  (my vote: +1)

      Vector mul (Vector b);
      Vector div (Vector b);

-1 It's unnecessary. If you want it to call a mul function, have the operator call it. Otherwise you can put all the code into the operator.
 2) "op_add", "op_mul", "op_div", etc.  (my vote: +1)

      Vector op_sub (Vector b);
      Vector op_mod (Vector b);

-1
 3) "operator +".  (my vote: -1)  My vote is because I find this syntax
 confusing in C++, particularly with its wide expressiveness, and I
 admire any syntax which doesn't require a change to tools, as the above
 don't.

      Vector operator + (Vector b);

-1 Screw the tools. Tools can change; it's early enough in the D lifecycle.
 4) 'operator "+"'.  (my vote: -0)  For some reason I find this less
 visually disconcerting.

      Vector operator "*" (Vector b);

-0 (Mainly it shouldn't be a member function)
 5) 'operator (a - b)' or 'operator (this - b)'.  (my vote: +0)  If I had
 to put in any new syntax I would prefer it to be this one.

      static Vector operator (a - b) (Vector a, Vector b);

+1 Although the static keyword is unnecessary; they should be able to be defined at global scope. Also the (a - b) part and (Vector a, Vector b) part should be able to be combined into one, something like: Vector operator ( (Vector a) - (Vector b) ) { return a.sub(b); }
 Now, where overloaded operators are defined:

 1) Operators are normal, possibly virtual methods in classes, normal
 nonvirtual methods in structs (My vote: +1).

      Vector add (Vector b);

-1 (though they can *call* methods)
 2) Overloaded operators are always static methods with both left and
 right arguments defined (My vote: 0).

      static Vector add (Vector a, Vector b);

+0
 3) Overloaded operators are global functions, using both arguments (My
 vote: -1).

      Vector add (Vector a, Vector b);

+1 (except for unary operators which have only one argument)
 4) Operator overloading shouldn't be put in (My vote: -1).

-99 ;) (ok, really -1)
 Now, reverse operator handling, where you want the right-side expression
 to handle the evaluation, such as with the form "int * Vector":

 1) A second set of potential functions (My vote: +1).

+1
 2) Automatic reorganization of the expression.  This makes assumptions
 about what the operators do and can't handle "1 / Vector" (My vote: -1).
   For example, "1-A" could become "-A+1".

-0 This could break some code.
 Now for the operations covered.  Please be temperate with your votes -
 operations can be added later, but they can't be removed as easily.

 1) a + b, a - b, a * b, a / b, a % b, -a, +a.  (my vote: +1)

+1
 2) a & b, a | b, a ^ b, ~a, !a.  (my vote: +1)

+0
 3) a++, a--, --a, ++a.  (my vote: 0)

+1
 4) a = b.  (my vote: 0)

+0 (This is really useful sometimes in C++, but I can live without it)
 5) a << b, a >> b, a >>> b.  (my vote: +1)

+0
 6) a += b, a -= b, a *= b, a %= b, etc.  (my vote: -1)

+1
 7) new, delete.  (my vote: -0)

+0 (I'd like some way to change allocation for a class, but not sure overriding new and delete is the best answer. Maybe flag the class as having a special allocator?)
 8) a || b, a && b.  (my vote: -1)

-0
 9) explicit a >= b, a > b, a <= b, a < b.  (my vote: -1)

+1 but it sure would be nice if you didn't have to provide them all (if you override a == b and a < b, it can generate all the other ones automatically)
 10) a [b].  (my vote: +1)

+1 (how else will you make custom containers?)
 10a) a [b] = c.  (my vote: +0)

+0 (this needs thought out more, but overriding assignment is useful sometimes)
 11) a [b .. c].  (my vote: +1)

+1 what the hell
 12) &a, *a.  (my vote: -1)

-0
 13) a.b, a.b = c.  Retrieve and assign property.  (my vote: +1)  Note
 that this won't allow just anything in b.

+0 existing property syntax handles this. Do you mean it can pass b in as a string?
 13a) a . b, where b can be any type.  (my vote: -1)

-1
 14) a ? b : c.  (my vote: -1)

-1 not needed, confusing
 15) a === b, a !== b.  (my vote: 0)

0
 16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my vote: 0)
 IMO this is an eq/cmp combination issue.

-1 I would only allow overriding == and <
 17) a in b.  (my vote: +1)

+0
 18) cast (b) a.  (my vote: -0)  I haven't had any good experiences with
 cast overloading in C++.

-1 me neither
 19) (a, b).  (my vote: -1)

-1 even though I've seen this put to good use in Spirit.
 And miscellaneous:

 1) Operator overloading should be allowed on basic types as global
 functions.  (my vote: -1)

      int operator "a - b" (int a, int b);

+0 So long as it's done through modules and doesn't automatically affect the entire program. It would be useful occasionally (rarely)
 2) Definition of new operators is allowed.  I'll ignore this one if it
 goes positive.  (my vote: -1)

      Vector operator (this dot b) (Vector b);

+1 would be very nice, but hard to implement. I'd like to allow high unicode symbols.
 2a) Setting precedence of new operators is allowed.  I'll ignore this
 one if it goes positive.  (my vote: -1)

      operator (a dot b) above (a >= b) below (a * b);

+0 would be nice, but it's hard to implement.
 I think that's about it.

Sean
Aug 09 2002
prev sibling next sibling parent reply Juarez Rudsatz <juarez nowhere.com> writes:
Burton Radons <loth users.sourceforge.net> wrote in 
news:3D5278B0.1000508 users.sourceforge.net:

 First off, the naming scheme:
 
 1) "add", "mul", "div", etc.  (my vote: +1)
 
      Vector mul (Vector b);
      Vector div (Vector b);

+1 y = Vector.mul(x); // should be allowed.
 2) "op_add", "op_mul", "op_div", etc.  (my vote: +1)
 
      Vector op_sub (Vector b);
      Vector op_mod (Vector b);

-0 Why not opAdd or OpMul or operatorAdd ?
 3) "operator +".  (my vote: -1)  My vote is because I find this syntax 
 confusing in C++, particularly with its wide expressiveness, and I 
 admire any syntax which doesn't require a change to tools, as the 

 don't.
 
      Vector operator + (Vector b);
 

-0
 4) 'operator "+"'.  (my vote: -0)  For some reason I find this less 
 visually disconcerting.
 
      Vector operator "*" (Vector b);
 

-1 This do not increase parser complexity. * is a token but "*" should be a token or a string. If a string, when it need to be interpreted?
 5) 'operator (a - b)' or 'operator (this - b)'.  (my vote: +0)  If I 

 to put in any new syntax I would prefer it to be this one.
 
      static Vector operator (a - b) (Vector a, Vector b);

-1 add new semantic problems: Vector operator (x - y) (Vector a, Vector b); and is similar to Vector operator + (Vector b); only with duplicated parameters.
 Now, where overloaded operators are defined:
 
 1) Operators are normal, possibly virtual methods in classes, normal 
 nonvirtual methods in structs (My vote: +1).
 
      Vector add (Vector b);

+1
 2) Overloaded operators are always static methods with both left and 
 right arguments defined (My vote: 0).
 
      static Vector add (Vector a, Vector b);

-0 Compared with (3), what this add ? Only the position of coding (within the class). But you could not make a additional operations module for another person module. But why separate? if you don't want maintaing that code but you trust in that person. if you need sync and dont wanna make modifications for that code (bug corrections).
 3) Overloaded operators are global functions, using both arguments (My 
 vote: -1).
 
      Vector add (Vector a, Vector b);

-0 This could be added later if are needs. And should be consistent with overloading for non-object types.
 4) Operator overloading shouldn't be put in (My vote: -1).

-1
 Now, reverse operator handling, where you want the right-side 

 to handle the evaluation, such as with the form "int * Vector":
 
 1) A second set of potential functions (My vote: +1).

+1
 2) Automatic reorganization of the expression.  This makes assumptions 
 about what the operators do and can't handle "1 / Vector" (My vote: -

   For example, "1-A" could become "-A+1".

-1
 Now for the operations covered.  Please be temperate with your votes - 
 operations can be added later, but they can't be removed as easily.

I tend to agree with you. except in:
 4) a = b.  (my vote: 0)

There are good questions here. 1) a = b + 1; // a and b are the same type is : a.replacedby(b.add(1)); or result = new resultype(); // similar with the above result.add(1); a.replacedby(result); delete result; or a.replacedby(b); a.add(1); 2) a = a + 1; is above or: a.add(1);
 13) a.b, a.b = c.  Retrieve and assign property.  (my vote: +1)  Note 
 that this won't allow just anything in b.

What the diference between the properties defined by Walter where a property is a simply procedure or function ?
 18) cast (b) a.  (my vote: -0)  I haven't had any good experiences
 with cast overloading in C++.

casting should be explicited in code : int a; currency x; a + x; // error a + cast(int) x; // ok If casting and assignment don't be allowed, for what uses op overloading could be used? I know this is problematic. But could have a restricted version of both.
 And miscellaneous:
 
 1) Operator overloading should be allowed on basic types as global 
 functions.  (my vote: -1)
 
      int operator "a - b" (int a, int b);

+1 For using with high performance computing like Currency, DateTime, Matematical calculations, ... This could not override built-in defined operations. Than one of operands _must_ be typedef'ed. int operator "a - b" (myType a, int b); And this follows the previous naming scheme: int add(myType a, int b);
 2) Definition of new operators is allowed.  I'll ignore this one if it 
 goes positive.  (my vote: -1)
 
      Vector operator (this dot b) (Vector b);

-0
 2a) Setting precedence of new operators is allowed.  I'll ignore this 
 one if it goes positive.  (my vote: -1)
 
      operator (a dot b) above (a >= b) below (a * b);

-1 If this will not be allowed now, this could be allowed later. Maybe could be a good decision stay with a little set of features allowing to be increased in future versions of language when the use could be justified by the need. -jr
Aug 09 2002
parent Mark Evans <Mark_member pathlink.com> writes:
Perhaps helpful ideas:

http://www.boost.org/libs/utility/operators.htm

Mark
Aug 09 2002
prev sibling next sibling parent reply "cblack01" <cblack01 cox.net> writes:
 2) Overloaded operators are always static methods with both left and
 right arguments defined (My vote: 0).

      static Vector add (Vector a, Vector b);

+1 Because we are dealing with a Vector-Vector relationship this makes sense, however ...
 3) Overloaded operators are global functions, using both arguments (My
 vote: -1).

    Vector add (Vector a, Vector b);

+1 Here we are dealing with relationships, not things specific to any particular object. Operator overloading actually fits the object-relational paradigm better than the object-oriented paradigm. I know OOP purists consider "global" to be morally wrong. But, tell me, to which object does this relationship belong? Vector mul (Vector a, Matrix b); We have a few options. We can put this relationship in the Vector class or we can put in the Matrix class. It's really not entirely clear where it belongs. But it makes more sense to me to define it outside of any class because it doesn't fit the OOP paradigm because it is a relationship between two objects. I'm sorry to burst you OOP purist bubble. Relationships do not fit OOP. Relationships fit the object-relational paradigm. Dare I say the word "multimethods"? Just my two very educated cents. Thanks for listening. Craig
Aug 10 2002
next sibling parent "Walter" <walter digitalmars.com> writes:
You do have a good point.

"cblack01" <cblack01 cox.net> wrote in message
news:aj4glg$e61$1 digitaldaemon.com...
 2) Overloaded operators are always static methods with both left and
 right arguments defined (My vote: 0).

      static Vector add (Vector a, Vector b);

+1 Because we are dealing with a Vector-Vector relationship this makes sense, however ...
 3) Overloaded operators are global functions, using both arguments (My
 vote: -1).

    Vector add (Vector a, Vector b);

+1 Here we are dealing with relationships, not things specific to any particular object. Operator overloading actually fits the

 paradigm better than the object-oriented paradigm.  I know OOP purists
 consider "global" to be morally wrong.  But, tell me, to which object does
 this relationship belong?

 Vector mul (Vector a, Matrix b);

 We have a few options.  We can put this relationship in the Vector class

 we can put in the Matrix class.  It's really not entirely clear where it
 belongs.  But it makes more sense to me to define it outside of any class
 because it doesn't fit the OOP paradigm because it is a relationship

 two objects.  I'm sorry to burst you OOP purist bubble. Relationships do

 fit OOP.  Relationships fit the object-relational paradigm.  Dare I say

 word "multimethods"?  Just my two very educated cents.

 Thanks for listening.

 Craig

Aug 11 2002
prev sibling parent reply Pavel Minayev <evilone omen.ru> writes:
On Sat, 10 Aug 2002 22:08:32 -0400 "cblack01" <cblack01 cox.net> wrote:

 We have a few options.  We can put this relationship in the Vector class or
 we can put in the Matrix class.  It's really not entirely clear where it
 belongs.  But it makes more sense to me to define it outside of any class
 because it doesn't fit the OOP paradigm because it is a relationship between
 two objects.  I'm sorry to burst you OOP purist bubble. Relationships do not
 fit OOP.  Relationships fit the object-relational paradigm.  Dare I say the
 word "multimethods"?  Just my two very educated cents.

In general, you're right. But me personally, I don't care much about OOP purity or something like that... tell me, in your scheme, how does an overloaded operator, being a global function, accesses private members of classes? It is almost always needed...
Aug 12 2002
parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
It doesn't;  it deals with the public interface of the class just like
everybody else.

Kinda makes me wish for friendship declarations but I'm not opposed to
putting "readable" member functions that actually do the work and simple
operators that just call those functions.  Gotta trust the compiler to
inline stuff properly though.  Those folks seriously opposed to operator
overloading can just use the "readable" versions directly.

That does bring up a point though.  How do you deal with this situation in
D?

class vector
{
private float x,y,z,w;
}

class matrix
{
private vector x,y,z,w;
}

vector operator (matrix a * vector b)
{
    return vector (a.x.x * b.x + a.x.y * b.y + a.x.z * b.z + a.x.w * b.w,
                          a.y.x * b.x + a.y.y * b.y + a.y.z * b.z + a.y.w *
b.w,
                          a.z.x * b.x + a.z.y * b.y + a.z.z * b.z + a.z.w *
b.w,
                          a.w.x * b.x + a.w.y * b.y + a.w.z * b.z + a.w.w *
b.w);
}

Won't compile because obviously xyzw are all private in both classes.  So
how to fix it?

class vector
{
private float x,y,z,w;
}

class matrix
{
private vector x,y,z,w;
public vector transform(vector b)
    {
        return vector (x.x * b.x + x.y * b.y + x.z * b.z + x.w * b.w,
                              y.x * b.x + y.y * b.y + y.z * b.z + y.w * b.w,
                              z.x * b.x + z.y * b.y + z.z * b.z + z.w * b.w,
                              w.x * b.x + w.y * b.y + w.z * b.z + w.w *
b.w);
    }
}

vector operator (matrix a * vector b)
{
    return a.transform(b);
}

That still doesn't work because matrix can't access members of vector.  And
it won't work if you put transform into class vector either.  Have to expose
some way to get at the private data, which kind of misses the point of
making it private to begin with.

For this kind of thing I'd probably just make the members public anyway (and
use structs instead of classes) just because I like to get at the members
easily and they rarely, if ever, change.  But it's not hard to imagine some
other situations like this.  Without "friend" in C++, how would you handle
this situation without violating the privacy of the classes?

Sean

"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374805064096759 news.digitalmars.com...
 On Sat, 10 Aug 2002 22:08:32 -0400 "cblack01" <cblack01 cox.net> wrote:

 We have a few options.  We can put this relationship in the Vector class


 we can put in the Matrix class.  It's really not entirely clear where it
 belongs.  But it makes more sense to me to define it outside of any


 because it doesn't fit the OOP paradigm because it is a relationship


 two objects.  I'm sorry to burst you OOP purist bubble. Relationships do


 fit OOP.  Relationships fit the object-relational paradigm.  Dare I say


 word "multimethods"?  Just my two very educated cents.

In general, you're right. But me personally, I don't care much about OOP purity or something like that... tell me, in your scheme, how does an overloaded operator, being a global function, accesses private members of classes? It is almost always needed...

Aug 13 2002
next sibling parent reply "Dario" <supdar yahoo.com> writes:
Probably, the simplest solution is to have user-defined opeators at global
level and let them access private member of the classes which they have as
arguments.
e.g.

class Vector
{
    private float x, y, z, w;
}

class Matrix
{
    private float x, y, z, w;
}

Vector operator(Vector a * Matrix b)
{
    /* here this function is able to access private members
    of classes Vector and Matrix */
}

I apologize if anyone has proposed this solution and it has been rejected
already.
___________________________________________________

 It doesn't;  it deals with the public interface of the class just like
 everybody else.

 Kinda makes me wish for friendship declarations but I'm not opposed to
 putting "readable" member functions that actually do the work and simple
 operators that just call those functions.  Gotta trust the compiler to
 inline stuff properly though.  Those folks seriously opposed to operator
 overloading can just use the "readable" versions directly.

 That does bring up a point though.  How do you deal with this situation in
 D?

 class vector
 {
 private float x,y,z,w;
 }

 class matrix
 {
 private vector x,y,z,w;
 }

 vector operator (matrix a * vector b)
 {
     return vector (a.x.x * b.x + a.x.y * b.y + a.x.z * b.z + a.x.w * b.w,
                           a.y.x * b.x + a.y.y * b.y + a.y.z * b.z + a.y.w

 b.w,
                           a.z.x * b.x + a.z.y * b.y + a.z.z * b.z + a.z.w

 b.w,
                           a.w.x * b.x + a.w.y * b.y + a.w.z * b.z + a.w.w

 b.w);
 }

 Won't compile because obviously xyzw are all private in both classes.  So
 how to fix it?

 class vector
 {
 private float x,y,z,w;
 }

 class matrix
 {
 private vector x,y,z,w;
 public vector transform(vector b)
     {
         return vector (x.x * b.x + x.y * b.y + x.z * b.z + x.w * b.w,
                               y.x * b.x + y.y * b.y + y.z * b.z + y.w *

                               z.x * b.x + z.y * b.y + z.z * b.z + z.w *

                               w.x * b.x + w.y * b.y + w.z * b.z + w.w *
 b.w);
     }
 }

 vector operator (matrix a * vector b)
 {
     return a.transform(b);
 }

 That still doesn't work because matrix can't access members of vector.

 it won't work if you put transform into class vector either.  Have to

 some way to get at the private data, which kind of misses the point of
 making it private to begin with.

 For this kind of thing I'd probably just make the members public anyway

 use structs instead of classes) just because I like to get at the members
 easily and they rarely, if ever, change.  But it's not hard to imagine

 other situations like this.  Without "friend" in C++, how would you handle
 this situation without violating the privacy of the classes?

 Sean

 We have a few options.  We can put this relationship in the Vector



 or
 we can put in the Matrix class.  It's really not entirely clear where



 belongs.  But it makes more sense to me to define it outside of any


 because it doesn't fit the OOP paradigm because it is a relationship


 two objects.  I'm sorry to burst you OOP purist bubble. Relationships



 not
 fit OOP.  Relationships fit the object-relational paradigm.  Dare I



 the
 word "multimethods"?  Just my two very educated cents.



 In general, you're right. But me personally, I don't care much about
 OOP purity or something like that... tell me, in your scheme, how does
 an overloaded operator, being a global function, accesses private
 members of classes? It is almost always needed...


Aug 13 2002
parent reply "anderson" <anderson firestar.com.au> writes:
"Dario" <supdar yahoo.com> wrote in message
news:ajb1or$14nq$1 digitaldaemon.com...
 Probably, the simplest solution is to have user-defined opeators at global
 level and let them access private member of the classes which they have as
 arguments.
 e.g.

 class Vector
 {
     private float x, y, z, w;
 }

 class Matrix
 {
     private float x, y, z, w;
 }

 Vector operator(Vector a * Matrix b)
 {
     /* here this function is able to access private members
     of classes Vector and Matrix */
 }

 I apologize if anyone has proposed this solution and it has been rejected
 already.

The major problem with that is, you open a portal for hackers and bad coding. People will missuse these operators simply for the sake of getting at private members when they should use other means. This would defeat the purpose of operators in the first place.
Aug 13 2002
parent reply "Dario" <supdar yahoo.com> writes:
 Probably, the simplest solution is to have user-defined opeators at


 level and let them access private member of the classes which they have


 arguments.
 e.g.

 class Vector
 {
     private float x, y, z, w;
 }

 class Matrix
 {
     private float x, y, z, w;
 }

 Vector operator(Vector a * Matrix b)
 {
     /* here this function is able to access private members
     of classes Vector and Matrix */
 }

 I apologize if anyone has proposed this solution and it has been


 already.


 The major problem with that is, you open a portal for hackers and bad
 coding. People will missuse these operators simply for the sake of getting
 at private members when they should use other means. This would defeat the
 purpose of operators in the first place.

I don't understand what you mean exactly. There are programming language which are OO but don't support class privacy (Python is an example). In these languages the interface is simply a convention which programmers aren't forced to respect. Is this agains the concept of OO programming? Moreover, since D supports pointer arithmetic you _can_ access private members that way. Ok, you will probably never want to, but "hacking" isn't totally prevented as you can see. But since D has the capability to change the member order, very few people will do such a "hack". Anyway shouldn't a programmer who want to access a private member simply make that member public modifying the class source code? (If the class is totally contained in an .obj file (as distributed classes usually are), you obviouly won't be able to write a new operator for that class, will you?)
Aug 13 2002
parent reply Pavel Minayev <evilone omen.ru> writes:
On Tue, 13 Aug 2002 21:10:27 +0200 "Dario" <supdar yahoo.com> wrote:

 Anyway shouldn't a programmer who want to access a private member simply
 make that member public modifying the class source code? (If the class is
 totally contained in an .obj file (as distributed classes usually are), you
 obviouly won't be able to write a new operator for that class, will you?)

Why not? You have the interface for the class, so what's the problem? Besides, it could be useful to glue libraries together: for example, in C++, you might want to overload << to output matrices from math lib to streams from STL. Neither class is yours (and you might not even have the source for them!), but overloading is possible. Anyhow, I think the "security reasons" aren't strong enough... if one really really needs to get to a private member somehow, it is in fact better to have at least portable solution (operator overloading) than using pointers... Misuse? Yes. And who cares? Overloading operator just to be able to access private member is a too complex solution to be used widely, so it might be used only by a few hackers here and there, mostly in low-level libs and such.
Aug 13 2002
parent reply Burton Radons <loth users.sourceforge.net> writes:
Pavel Minayev wrote:
 On Tue, 13 Aug 2002 21:10:27 +0200 "Dario" <supdar yahoo.com> wrote:
 
 
Anyway shouldn't a programmer who want to access a private member simply
make that member public modifying the class source code? (If the class is
totally contained in an .obj file (as distributed classes usually are), you
obviouly won't be able to write a new operator for that class, will you?)

Why not? You have the interface for the class, so what's the problem? Besides, it could be useful to glue libraries together: for example, in C++, you might want to overload << to output matrices from math lib to streams from STL. Neither class is yours (and you might not even have the source for them!), but overloading is possible.

 Anyhow, I think the "security reasons" aren't strong enough... if one really
 really needs to get to a private member somehow, it is in fact better to
 have at least portable solution (operator overloading) than using pointers...
 Misuse? Yes. And who cares? Overloading operator just to be able to access
 private member is a too complex solution to be used widely, so it might be
 used only by a few hackers here and there, mostly in low-level libs and such.

Hm. Well, since security is intended as protection for the end-user, and emphatically not like lock box security, perhaps it should be spoofable a la const: (public) a.x; Or if that's not noticeable enough: cast (public) a.x; Thus the preference will be to use properties and methods to manipulate a class's internals, but there's a recourse if the class was incorrectly written. I've always been troubled about C++'s lack of recourse; it makes bad situations a gazillion times worse. I almost always use "// private:" and "// protected:" simply because of this.
Aug 13 2002
next sibling parent reply "anderson" <anderson firestar.com.au> writes:
Good idea, still kinda breaks data abstraction. However, it means strong
typing ;).

Perhaps something like:

access(a)
{
    a.x = ...;
    a.b = ...;
}

Parhaps there could be something known as strong privates and protected that
still can't be accessed:

strong private:
    int x;

strong protected:
    int y;

This way you could still protect you data abstraction if you really need to.
I think that'll satify both groups.


"Burton Radons" <loth users.sourceforge.net> wrote in message
news:3D597876.9080108 users.sourceforge.net...
 Pavel Minayev wrote:
 On Tue, 13 Aug 2002 21:10:27 +0200 "Dario" <supdar yahoo.com> wrote:


Anyway shouldn't a programmer who want to access a private member simply
make that member public modifying the class source code? (If the class



totally contained in an .obj file (as distributed classes usually are),



obviouly won't be able to write a new operator for that class, will



 Why not? You have the interface for the class, so what's the problem?
 Besides, it could be useful to glue libraries together: for example, in
 C++, you might want to overload << to output matrices from math lib
 to streams from STL. Neither class is yours (and you might not even
 have the source for them!), but overloading is possible.

 Anyhow, I think the "security reasons" aren't strong enough... if one


 really needs to get to a private member somehow, it is in fact better to
 have at least portable solution (operator overloading) than using


 Misuse? Yes. And who cares? Overloading operator just to be able to


 private member is a too complex solution to be used widely, so it might


 used only by a few hackers here and there, mostly in low-level libs and


 Hm.  Well, since security is intended as protection for the end-user,
 and emphatically not like lock box security, perhaps it should be
 spoofable a la const:

      (public) a.x;

 Or if that's not noticeable enough:

      cast (public) a.x;

 Thus the preference will be to use properties and methods to manipulate
 a class's internals, but there's a recourse if the class was incorrectly
 written.  I've always been troubled about C++'s lack of recourse; it
 makes bad situations a gazillion times worse.  I almost always use "//
 private:" and "// protected:" simply because of this.

Aug 13 2002
parent reply Pavel Minayev <evilone omen.ru> writes:
On Wed, 14 Aug 2002 11:04:22 +0800 "anderson" <anderson firestar.com.au> wrote:

 Parhaps there could be something known as strong privates and protected that
 still can't be accessed:
 
 strong private:
     int x;
 
 strong protected:
     int y;

If there's something that is forbidden, there will be someone who needs it badly!
 This way you could still protect you data abstraction if you really need to.
 I think that'll satify both groups.

I don't think one really needs to protect data abstraction to that level. A simple private declaration would be enough to tell both the compiler and the user that this member is not to be messed with. If the user, for some reason, decides to, it should be his right - and his problems. =)
Aug 14 2002
parent "anderson" <anderson firestar.com.au> writes:
Parhaps if with statements are included:

with (private) a;
{
    .x = ..
    .y = ..

}
Just to save on that messy casting (but also alow casting of course).


"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374824929020255 news.digitalmars.com...
 On Wed, 14 Aug 2002 11:04:22 +0800 "anderson" <anderson firestar.com.au>

 Parhaps there could be something known as strong privates and protected


 still can't be accessed:

 strong private:
     int x;

 strong protected:
     int y;

If there's something that is forbidden, there will be someone who needs it badly!
 This way you could still protect you data abstraction if you really need


 I think that'll satify both groups.

I don't think one really needs to protect data abstraction to that level. A simple private declaration would be enough to tell both the compiler and the user that this member is not to be messed with. If the user, for some reason, decides to, it should be his right - and his problems. =)

Aug 15 2002
prev sibling parent Pavel Minayev <evilone omen.ru> writes:
On Tue, 13 Aug 2002 14:21:58 -0700 Burton Radons <loth users.sourceforge.net> 
wrote:

 Hm.  Well, since security is intended as protection for the end-user, 
 and emphatically not like lock box security, perhaps it should be 
 spoofable a la const:
 
      (public) a.x;
 
 Or if that's not noticeable enough:
 
      cast (public) a.x;

This one seems to be a neat solution to all problems! No friend declarations etc, but you're still able to play with private data as you like when it comes to that. And the syntax is rather clear. I vote +1.
Aug 14 2002
prev sibling next sibling parent reply "anderson" <anderson firestar.com.au> writes:
Yes, I was considering this last week. This was when I was talking about
using some type of protection mechinism (permission) like lynux does rwx rwx
rwx (i think...). So you could put classes into differn't groups with
differn't permissions. This of course would have other added advantages. It
could be applied at the package, class, method and private method. Private,
protected and public would still apply. However I don't know how this would
look (it should be simple and small).

Java allows packages to access private members in that package. That's a
simular but more basic approach to this idea.

The standard method in C++ was to return each member by a get/set witch was
laborious and sometimes broke a class.

I think Pavel indicates that the his static version idea could have access
to both (or the present???) class privates.

"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:ajac46$fg0$1 digitaldaemon.com...
 It doesn't;  it deals with the public interface of the class just like
 everybody else.

 Kinda makes me wish for friendship declarations but I'm not opposed to
 putting "readable" member functions that actually do the work and simple
 operators that just call those functions.  Gotta trust the compiler to
 inline stuff properly though.  Those folks seriously opposed to operator
 overloading can just use the "readable" versions directly.

 That does bring up a point though.  How do you deal with this situation in
 D?

 class vector
 {
 private float x,y,z,w;
 }

 class matrix
 {
 private vector x,y,z,w;
 }

 vector operator (matrix a * vector b)
 {
     return vector (a.x.x * b.x + a.x.y * b.y + a.x.z * b.z + a.x.w * b.w,
                           a.y.x * b.x + a.y.y * b.y + a.y.z * b.z + a.y.w

 b.w,
                           a.z.x * b.x + a.z.y * b.y + a.z.z * b.z + a.z.w

 b.w,
                           a.w.x * b.x + a.w.y * b.y + a.w.z * b.z + a.w.w

 b.w);
 }

 Won't compile because obviously xyzw are all private in both classes.  So
 how to fix it?

 class vector
 {
 private float x,y,z,w;
 }

 class matrix
 {
 private vector x,y,z,w;
 public vector transform(vector b)
     {
         return vector (x.x * b.x + x.y * b.y + x.z * b.z + x.w * b.w,
                               y.x * b.x + y.y * b.y + y.z * b.z + y.w *

                               z.x * b.x + z.y * b.y + z.z * b.z + z.w *

                               w.x * b.x + w.y * b.y + w.z * b.z + w.w *
 b.w);
     }
 }

 vector operator (matrix a * vector b)
 {
     return a.transform(b);
 }

 That still doesn't work because matrix can't access members of vector.

 it won't work if you put transform into class vector either.  Have to

 some way to get at the private data, which kind of misses the point of
 making it private to begin with.

 For this kind of thing I'd probably just make the members public anyway

 use structs instead of classes) just because I like to get at the members
 easily and they rarely, if ever, change.  But it's not hard to imagine

 other situations like this.  Without "friend" in C++, how would you handle
 this situation without violating the privacy of the classes?

 Sean

 "Pavel Minayev" <evilone omen.ru> wrote in message
 news:CFN374805064096759 news.digitalmars.com...
 On Sat, 10 Aug 2002 22:08:32 -0400 "cblack01" <cblack01 cox.net> wrote:

 We have a few options.  We can put this relationship in the Vector



 or
 we can put in the Matrix class.  It's really not entirely clear where



 belongs.  But it makes more sense to me to define it outside of any


 because it doesn't fit the OOP paradigm because it is a relationship


 two objects.  I'm sorry to burst you OOP purist bubble. Relationships



 not
 fit OOP.  Relationships fit the object-relational paradigm.  Dare I



 the
 word "multimethods"?  Just my two very educated cents.

In general, you're right. But me personally, I don't care much about OOP purity or something like that... tell me, in your scheme, how does an overloaded operator, being a global function, accesses private members of classes? It is almost always needed...


Aug 13 2002
parent Pavel Minayev <evilone omen.ru> writes:
On Tue=2C 13 Aug 2002 21=3A53=3A49 +0800 =22anderson=22
=3Canderson=40firestar=2Ecom=2Eau=3E wrote=3A

=3E Java allows packages to access private members in that package=2E That's a
=3E simular but more basic approach to this idea=2E

This is basically the same as C++'s friend=2C only applied automatically=2E
 
=3E I think Pavel indicates that the his static version idea could have access
=3E to both =28or the present=3F=3F=3F=29 class privates=2E

Well=2C any static function can access class privates=2E But only the one
it resides in=2E

My first proposal was that operator can access private members of
classes of operands and result=2E For example=3A

=09Foo operator=28Bar a + Baz b=29=3B

This one can access private members of classes Foo=2C Bar and Baz directly=2E
Kinda auto-friend again=2E Unless you care much of OOP purity=2C it seems the
simplest =28both to implement and to use=29 approach=2E=2E=2E
Aug 13 2002
prev sibling parent "Walter" <walter digitalmars.com> writes:
"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:ajac46$fg0$1 digitaldaemon.com...
 For this kind of thing I'd probably just make the members public anyway

 use structs instead of classes) just because I like to get at the members
 easily and they rarely, if ever, change.  But it's not hard to imagine

 other situations like this.  Without "friend" in C++, how would you handle
 this situation without violating the privacy of the classes?

It's an interesting problem. I just don't like the C++ "friend" syntax and semantics. There's got to be a better way.
Aug 13 2002
prev sibling next sibling parent reply "Walter" <walter digitalmars.com> writes:
"Burton Radons" <loth users.sourceforge.net> wrote in message
news:3D5278B0.1000508 users.sourceforge.net...
 Now, reverse operator handling, where you want the right-side expression
 to handle the evaluation, such as with the form "int * Vector":

 1) A second set of potential functions (My vote: +1).

 2) Automatic reorganization of the expression.  This makes assumptions
 about what the operators do and can't handle "1 / Vector" (My vote: -1).
   For example, "1-A" could become "-A+1".

It just occurred to me (I apologize if I missed someone else posting it) that the language can make the commutative operators (+, *, |, &, etc.) commutative even with operator overloads, with the proviso that if a reverse overload was provided, that would be used instead. For example: class A { A add(int); } A a; a+1 => a.add(1) 1+a => a.add(1) But if: class A { A add(int); A add_r(int); } A a; a+1 => a.add(1) 1+a => a.add_r(1) This seems to have the advantage of both schemes, and minimizes the need for a plethora of functions being defined just for swizzling the arguments.
Aug 11 2002
parent reply "anderson" <anderson firestar.com.au> writes:
Right, but what about?

class A
{
    A add(B);
    A add_r(B);
}

class B
{
    B add(A);
    B add_r(A);
}

I suppose this may be illegal?

A a;
B b;
a+b => a.add(b) & b.add(a)
b+a => a.add_r(b) & b.add_r(a)


"Walter" <walter digitalmars.com> wrote in message
news:aj6gbt$2c7b$1 digitaldaemon.com...
 "Burton Radons" <loth users.sourceforge.net> wrote in message
 news:3D5278B0.1000508 users.sourceforge.net...
 Now, reverse operator handling, where you want the right-side expression
 to handle the evaluation, such as with the form "int * Vector":

 1) A second set of potential functions (My vote: +1).

 2) Automatic reorganization of the expression.  This makes assumptions
 about what the operators do and can't handle "1 / Vector" (My vote: -1).
   For example, "1-A" could become "-A+1".

It just occurred to me (I apologize if I missed someone else posting it) that the language can make the commutative operators (+, *, |, &, etc.) commutative even with operator overloads, with the proviso that if a

 overload was provided, that would be used instead. For example:

 class A
 {
     A add(int);
 }

 A a;
 a+1 => a.add(1)
 1+a => a.add(1)

 But if:

 class A
 {
     A add(int);
     A add_r(int);
 }

 A a;
 a+1 => a.add(1)
 1+a => a.add_r(1)

 This seems to have the advantage of both schemes, and minimizes the need

 a plethora of functions being defined just for swizzling the arguments.

Aug 11 2002
parent "Walter" <walter digitalmars.com> writes:
It should give an ambiguity error.

"anderson" <anderson firestar.com.au> wrote in message
news:aj74ij$2v6e$1 digitaldaemon.com...
 Right, but what about?

 class A
 {
     A add(B);
     A add_r(B);
 }

 class B
 {
     B add(A);
     B add_r(A);
 }

 I suppose this may be illegal?

 A a;
 B b;
 a+b => a.add(b) & b.add(a)
 b+a => a.add_r(b) & b.add_r(a)

Aug 11 2002
prev sibling next sibling parent "Dario" <supdar yahoo.com> writes:
Here are my votes

 I've accidentally implemented operator overloading in my port.  It was
 kind of incidental to other work, so I thought "what the hell" and threw
 it in.  But this brings up the whole issue of syntax, and I think that
 should be voted on to specify the syntax on my side and to influence
 Walter when he decides to do this topic.

 I'd like Apache-style voting to be used, where the voting is either -1,
 -0, 0, +0, or +1 for any option, which is a good bellweather of how
 people think about something.

 First off, the naming scheme:

 1) "add", "mul", "div", etc.  (my vote: +1)

      Vector mul (Vector b);
      Vector div (Vector b);

+0
 2) "op_add", "op_mul", "op_div", etc.  (my vote: +1)

      Vector op_sub (Vector b);
      Vector op_mod (Vector b);

-0
 3) "operator +".  (my vote: -1)  My vote is because I find this syntax
 confusing in C++, particularly with its wide expressiveness, and I
 admire any syntax which doesn't require a change to tools, as the above
 don't.

      Vector operator + (Vector b);

-0
 4) 'operator "+"'.  (my vote: -0)  For some reason I find this less
 visually disconcerting.

      Vector operator "*" (Vector b);

-0
 5) 'operator (a - b)' or 'operator (this - b)'.  (my vote: +0)  If I had
 to put in any new syntax I would prefer it to be this one.

      static Vector operator (a - b) (Vector a, Vector b);

+0 Even better the sintax someone has proposed: // global function Vector operator(Vector a - Vector b);
 Now, where overloaded operators are defined:

 1) Operators are normal, possibly virtual methods in classes, normal
 nonvirtual methods in structs (My vote: +1).

      Vector add (Vector b);

0 This vote is because the compiler won't be able to choose between a.add(b) and b.addr(a). The compiler will emit an ambiguity error and this will be _very_ frustrating to fix.
 2) Overloaded operators are always static methods with both left and
 right arguments defined (My vote: 0).

      static Vector add (Vector a, Vector b);

-1 Static operators are not overridable.
 3) Overloaded operators are global functions, using both arguments (My
 vote: -1).

      Vector add (Vector a, Vector b);

+1
 4) Operator overloading shouldn't be put in (My vote: -1).

-0 (to be sincere I have rarely used it...)
 Now, reverse operator handling, where you want the right-side expression
 to handle the evaluation, such as with the form "int * Vector":
 1) A second set of potential functions (My vote: +1).

+1
 2) Automatic reorganization of the expression.  This makes assumptions
 about what the operators do and can't handle "1 / Vector" (My vote: -1).
   For example, "1-A" could become "-A+1".

-1
 Now for the operations covered.  Please be temperate with your votes -
 operations can be added later, but they can't be removed as easily.

 1) a + b, a - b, a * b, a / b, a % b, -a, +a.  (my vote: +1)

+1
 2) a & b, a | b, a ^ b, ~a, !a.  (my vote: +1)

+1
 3) a++, a--, --a, ++a.  (my vote: 0)

-0 This should be equivalent to a = a + 1, etc.
 4) a = b.  (my vote: 0)

+0
 5) a << b, a >> b, a >>> b.  (my vote: +1)

+1
 6) a += b, a -= b, a *= b, a %= b, etc.  (my vote: -1)

-1 This should always be equivalent to a = a + b, etc.
 7) new, delete.  (my vote: -0)

0
 8) a || b, a && b.  (my vote: -1)

+0 Why not???
 9) explicit a >= b, a > b, a <= b, a < b.  (my vote: -1)

+0 If we let op= to be overloaded, why not these?
 10) a [b].  (my vote: +1)

+1
 10a) a [b] = c.  (my vote: +0)

+1 Maybe there is a way to use settors?
 11) a [b .. c].  (my vote: +1)

+1
 12) &a, *a.  (my vote: -1)

-1
 13) a.b, a.b = c.  Retrieve and assign property.  (my vote: +1)  Note
 that this won't allow just anything in b.

-1 What is this needed for?
 13a) a . b, where b can be any type.  (my vote: -1)

-1
 14) a ? b : c.  (my vote: -1)

-1
 15) a === b, a !== b.  (my vote: 0)

-1
 16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my vote: 0)
 IMO this is an eq/cmp combination issue.

+0
 17) a in b.  (my vote: +1)

+1
 18) cast (b) a.  (my vote: -0)  I haven't had any good experiences with
 cast overloading in C++.

-1
 19) (a, b).  (my vote: -1)

-1 Why a(b) not? This gets +0
 And miscellaneous:

 1) Operator overloading should be allowed on basic types as global
 functions.  (my vote: -1)

      int operator "a - b" (int a, int b);

-1 This invalidates code.
 2) Definition of new operators is allowed.  I'll ignore this one if it
 goes positive.  (my vote: -1)

      Vector operator (this dot b) (Vector b);

0
 2a) Setting precedence of new operators is allowed.  I'll ignore this
 one if it goes positive.  (my vote: -1)

      operator (a dot b) above (a >= b) below (a * b);

-1 This is too error-prone.
 I think that's about it.

Aug 13 2002
prev sibling next sibling parent reply Burton Radons <loth users.sourceforge.net> writes:
The polls are closed.  I'll try to pool the write-in candidates.  For 
summing, -1, -0, 0, +0, and +1 are recorded as -2, -1, 0, +1, and +2.

 1) "add", "mul", "div", etc.  (my vote: +1)
 
     Vector mul (Vector b);
     Vector div (Vector b);

+0, -1, +1, +1, +0, -1, +1, +0 = 2.5/8 = +0.3125 My vote on this has changed to +0. Although I'm not sure I like the syntax, "((Vector a) * (extended b))" is definitely clearer and handles reverse and the post/pre-increment/decrement far more elegantly.
 2) "op_add", "op_mul", "op_div", etc.  (my vote: +1)
 
     Vector op_sub (Vector b);
     Vector op_mod (Vector b);

+0, -1, +1, 0, 0, -1, -0, -0 = -3/8 = -0.375 Juarez suggested "opAdd" or "operator Add".
 3) "operator +".  (my vote: -1)  My vote is because I find this syntax 
 confusing in C++, particularly with its wide expressiveness, and I 
 admire any syntax which doesn't require a change to tools, as the above 
 don't.
 
     Vector operator + (Vector b);

-1, +0, -1, 0, -0, -1, -0, -0 = -8/8 = -1
 4) 'operator "+"'.  (my vote: -0)  For some reason I find this less 
 visually disconcerting.
 
     Vector operator "*" (Vector b);

-0, -0, -0, +1, 0, -0, -1, -0 = -5/8 = -0.625 Pavel suggested (*). My preference here was because it causes the syntax highlighter to mark it nicely, so it doesn't get lost in a sea of parentheses.
 5) 'operator (a - b)' or 'operator (this - b)'.  (my vote: +0)  If I had 
 to put in any new syntax I would prefer it to be this one.
 
     static Vector operator (a - b) (Vector a, Vector b);

+0, 0, +0, +1, +1, -1, +0 = 5/7 = 0.7143 Pavel, you didn't +1 anything here. Do you have any syntax in mind, or are they all equally evil? C.R. suggested "static Vector sub operator (a - b) (Vector a, Vector b)". I'll merge this with "static Vector operator (Vector a - Vector b)". If I decide to use this - and it seems quite likely - then I'll get more opinions there.
 1) Operators are normal, possibly virtual methods in classes, normal 
 nonvirtual methods in structs (My vote: +1).
 
     Vector add (Vector b);

+1, -1, +1, +1, +0, -1, +1, 0 = 5/8 = 0.625
 2) Overloaded operators are always static methods with both left and 
 right arguments defined (My vote: 0).
 
     static Vector add (Vector a, Vector b);

0, +1, +0, -1, 0, +0, -0, +1, -1 = 1/9 = 0.111
 3) Overloaded operators are global functions, using both arguments (My 
 vote: -1).
 
     Vector add (Vector a, Vector b);

-1, -0, -0, -1, -0, +1, -0, +1, +1 = -2/9 = 0.222
 4) Operator overloading shouldn't be put in (My vote: -1).

-1, -1, -0, -1, -1, -1, -0 = -12/7 = -1.714 Honesty much appreciated, Dario.
 Now, reverse operator handling, where you want the right-side expression 
 to handle the evaluation, such as with the form "int * Vector":
 
 1) A second set of potential functions (My vote: +1).

+1, +1, +1, +1, +0, +1, +1, +1 = 15/8 = 1.875
 2) Automatic reorganization of the expression.  This makes assumptions 
 about what the operators do and can't handle "1 / Vector" (My vote: -1). 
  For example, "1-A" could become "-A+1".

-1, -1, -1, -1, -0, -0, -1, -1 = -14/8 = -1.75
 Now for the operations covered.  Please be temperate with your votes - 
 operations can be added later, but they can't be removed as easily.
 
 1) a + b, a - b, a * b, a / b, a % b, -a, +a.  (my vote: +1)

+1, +1, +1, +1, +1, +1, +1 = 14/7 = 2 Patrick reminded me about a ~ b. I'll pool that with (10).
 2) a & b, a | b, a ^ b, ~a, !a.  (my vote: +1)

+1, +1, +1, +1, +1, +0, -1, +1 = 11/8 = 1.375
 3) a++, a--, --a, ++a.  (my vote: 0)

0, +1, +1, +1, +0, +1, -0 = 8/7 = 1.1429
 4) a = b.  (my vote: 0)

-1, -0, -1, +1, -0, +0, +0 = -2/7 = -0.2857 I changed my vote.
 5) a << b, a >> b, a >>> b.  (my vote: +1)

+1, +0, +1, 0, +1, +1, +1 = 11/7 = 1.5714
 6) a += b, a -= b, a *= b, a %= b, etc.  (my vote: -1)

-1, -0, +0, -0, +1, -1 = -3/6 = -0.5
 7) new, delete.  (my vote: -0)

-0, -1, +1, -1, -1, +0, 0 = -4/7 = -0.5714
 8) a || b, a && b.  (my vote: -1)

-1, 0, -1, +1, +0, -0, +0 = -1/7 = -0.1429 The argument against this one is that like the trinary operator, it's impossible to duplicate the current semantics. The builtin and the overloaded operator are not the same in any way, so it seems wrong to give them the same name. Being able to test for nonzero is helpful, though.
 9) explicit a >= b, a > b, a <= b, a < b.  (my vote: -1)

-1, +1, -1, +1, +0, +1, +0 = 4/7 = 0.5714 This confused some people. You can already overload cmp, which already gives enough information to do these operators. I don't see how one could require more than that without breaking the basic meaning of the operators - and I definitely don't see any reason to care about people who WANT to break the basic meaning of the operators.
 10) a [b].  (my vote: +1)

+1, +1, +1, +1, -0, +1, +1 = 11/7 = 1.5714
 10a) a [b] = c.  (my vote: +0)

+0, +1, +1, 0, -1, +0, +1 = 6/7 = 0.8571
 11) a [b .. c].  (my vote: +1)

+1, +1, +1, +1, 0, +1, +1 = 12/7 = 1.7143
 12) &a, *a.  (my vote: -1)

-1, -1, -1, -1, -1, -0, -1 = 13/7 = -1.8571
 13) a.b, a.b = c.  Retrieve and assign property.  (my vote: +1)  Note 
 that this won't allow just anything in b.

+1, 0, +1, 0, 0, +0, -1 = 3/7 = 0.4286 Another one that confused people. A sample: struct PyObject { PyObject operator getattr (char [] name) { PyObject string, result; string = new PyStringObject (name); result = type.getAttr (string); string.decref (); return incref (result); } } py.foo; /* Calls getattr if the field doesn't exist otherwise */
 13a) a . b, where b can be any type.  (my vote: -1)

-1, -1, -1, -1, -0, -1, -1 = -13/7 = -1.8571
 14) a ? b : c.  (my vote: -1)

-1, -1, -1, -1, 0, -1, -1 = -12/7 = -1.7143
 15) a === b, a !== b.  (my vote: 0)

0, 0, -1, 0, -0, 0, -1 = -5/8 = -0.625
 16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my vote: 0) IMO 
 this is an eq/cmp combination issue.

0, +1, 0, 0, +0, -1, +0 = 2/7 = 0.2857 The same argument as >=, >, <, <= above. This is simply implemented as a combination of eq and cmp, which expresses everything we need to do these properly. Explicitly allowing them is confusing.
 17) a in b.  (my vote: +1)

+1, 0, +1, +1, +1, +0, +1 = 11/7 = 1.5714
 18) cast (b) a.  (my vote: -0)  I haven't had any good experiences with 
 cast overloading in C++.

-1, -0, -1, +1, +0, -1, -1 = -6/7 = -0.8571
 19) (a, b).  (my vote: -1)

-1, -1, -1, -1, -1, -1, -1 = -14/7 = -2 Dario reminded me of a(b). Forgot about that one. I can't pool that into any other operator, so is anyone opposed to it?
 And miscellaneous:
 
 1) Operator overloading should be allowed on basic types as global 
 functions.  (my vote: -1)
 
     int operator "a - b" (int a, int b);

-1, +1, 0, -1, 0, +0, +1, -1
 2) Definition of new operators is allowed.  I'll ignore this one if it 
 goes positive.  (my vote: -1)
 
     Vector operator (this dot b) (Vector b);

-1, -1, 0, -1, +1, +1, -0, 0 = -3/8 = -0.375 Patrick suggested allowing "a.func (b)" to be written as "a func b". IMO they mean the exact same thing, I just can't figure out what precedence the second is given. Most of the time you'd write "(a func b)" to be clear, at which point you're saving no characters at all, so why not express it normally?
 2a) Setting precedence of new operators is allowed.  I'll ignore this 
 one if it goes positive.  (my vote: -1)
 
     operator (a dot b) above (a >= b) below (a * b);

-1, -1, -1, 0, +1, +0, +0, -1, -1 = -6/9 = -0.6667
Aug 16 2002
next sibling parent Burton Radons <loth users.sourceforge.net> writes:
Burton Radons wrote:

 And miscellaneous:

 1) Operator overloading should be allowed on basic types as global 
 functions.  (my vote: -1)

     int operator "a - b" (int a, int b);

-1, +1, 0, -1, 0, +0, +1, -1

Oops. This sums to zero.
Aug 16 2002
prev sibling next sibling parent reply Pavel Minayev <evilone omen.ru> writes:
On Fri, 16 Aug 2002 19:49:01 -0700 Burton Radons <loth users.sourceforge.net> 
wrote:

 Pavel, you didn't +1 anything here.  Do you have any syntax in mind, or 
 are they all equally evil?

Citing myself: =)
 16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my vote: 0) IMO 
 this is an eq/cmp combination issue.

The same argument as >=, >, <, <= above. This is simply implemented as a combination of eq and cmp, which expresses everything we need to do these properly. Explicitly allowing them is confusing.

This is NOT just a simple combination of eq() and cmp() - how would you express D floating-point comparisons (RTFM!) this way?
Aug 17 2002
parent reply Burton Radons <loth users.sourceforge.net> writes:
Pavel Minayev wrote:

 On Fri, 16 Aug 2002 19:49:01 -0700 Burton Radons

 wrote:


 Pavel, you didn't +1 anything here.  Do you have any syntax in
 mind, or are they all equally evil?

Citing myself: =)
 16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my
 vote: 0) IMO this is an eq/cmp combination issue.

implemented as a combination of eq and cmp, which expresses everything we need to do these properly. Explicitly allowing them is confusing.

This is NOT just a simple combination of eq() and cmp() - how would you express D floating-point comparisons (RTFM!) this way?

Through a simple combination of eq and cmp (with bugs, indubitably): == is eq != is !eq
 is cmp > 0
= is cmp >= 0 or eq

<= is cmp <= 0 or eq !<>= is !cmp and !eq <> is cmp <>= is cmp or eq !<= is cmp <= 0 or !eq !< is cmp < 0 or !eq !>= is cmp >= 0 or !eq !> is cmp > 0 or !eq !<> is cmp or !eq For the operations which can throw exceptions, we could leave them alone if only cmp or eq are overloaded, and throw if they're incompatible - for example, with <=, if cmp returns zero but eq returns false, it's unordered, hence one is NaN and an exception can be thrown. Walter, could you back one of us up here, please?
Aug 17 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Burton Radons" <loth users.sourceforge.net> wrote in message
news:3D5F0476.1060203 users.sourceforge.net...
 Walter, could you back one of us up here, please?

I think it will work right if: a op b is rewritten as: a.cmp(b) op 0 For the nan cases, the cmp function can return nan's.
Aug 18 2002
next sibling parent reply Pavel Minayev <evilone omen.ru> writes:
On Sun, 18 Aug 2002 16:47:56 -0700 "Walter" <walter digitalmars.com> wrote:

 I think it will work right if:
     a op b
 is rewritten as:
     a.cmp(b) op 0
 For the nan cases, the cmp function can return nan's.

Then cmp() needs to be defined as "float cmp(a, b)".
Aug 18 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374873976712963 news.digitalmars.com...
 On Sun, 18 Aug 2002 16:47:56 -0700 "Walter" <walter digitalmars.com>

 I think it will work right if:
     a op b
 is rewritten as:
     a.cmp(b) op 0
 For the nan cases, the cmp function can return nan's.

Then cmp() needs to be defined as "float cmp(a, b)".

Yes - you can define it to return anything you want <g>.
Aug 19 2002
parent reply Pavel Minayev <evilone omen.ru> writes:
On Mon, 19 Aug 2002 17:52:08 -0700 "Walter" <walter digitalmars.com> wrote:

 Then cmp() needs to be defined as "float cmp(a, b)".

Yes - you can define it to return anything you want <g>.

Doesn't Object define it as int cmp() already?
Aug 20 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374884975017593 news.digitalmars.com...
 Doesn't Object define it as int cmp() already?

Correct. But if you overload it, you can change the return type - but be aware that will create more than one entry for cmp in the vtbl[].
Aug 20 2002
next sibling parent reply Joe Battelle <Joe_member pathlink.com> writes:
Correct. But if you overload it, you can change the return type - but be
aware that will create more than one entry for cmp in the vtbl[].

accurate <g>. It might be good if you could overload based on just the return type--but you can't in the current implementation. For example, this bogus code won't compile: class A { int neg() { return -1; } char[] neg() { return "-1"; } void neg() { assert(false); } } void foo() { A a; -a; int i = -a; char[] s = -a; } Though, FWIW, it should be noted that if you fudge the return type of neg to void and don't provide the other overloads, you can keep the operator from being used to create an rvalue.
Aug 20 2002
parent "Walter" <walter digitalmars.com> writes:
"Joe Battelle" <Joe_member pathlink.com> wrote in message
news:aju8ag$1s8n$1 digitaldaemon.com...
Correct. But if you overload it, you can change the return type - but be
aware that will create more than one entry for cmp in the vtbl[].

accurate <g>. It might be good if you could overload based on just the

 type--but you can't in the current implementation.

What you'd have to do for cmp is provide two functions: class MyFloat { int cmp(Object o); float cmp(MyFloat f); }
Aug 21 2002
prev sibling parent reply Pavel Minayev <evilone omen.ru> writes:
On Tue=2C 20 Aug 2002 11=3A33=3A34 -0700 =22Walter=22
=3Cwalter=40digitalmars=2Ecom=3E wrote=3A

=3E Correct=2E But if you overload it=2C you can change the return type - but be
=3E aware that will create more than one entry for cmp in the vtbl=5B=5D=2E
 
Then=2C take a look at this=3A

=09class Foo
=09{
=09=09float cmp=28=29 { =2E=2E=2E }
=09}

=09void process=28Object a=2C Object b=29
=09{
=09=09if =28a =3C b=29
=09=09=09=2E=2E=2E
=09=09else
=09=09=09=2E=2E=2E
=09}

=09int main=28=29
=09{
=09=09process=28new Foo=2C new Foo=29=3B
=09}

Now=2C which version of cmp=28=29 will be used in process=28=29=3F
 
Aug 20 2002
parent reply "Walter" <walter digitalmars.com> writes:
The
    int Foo.cmp(Object o);
version will be used. Since process() doesn't know about NaN's anyway,
you'll need to overload int cmp(Object o); to perhaps throw an exception on
a NaN, and then write a float cmp(MyFloat o) to handle NaN's.

"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374890162473958 news.digitalmars.com...
On Tue, 20 Aug 2002 11:33:34 -0700 "Walter" <walter digitalmars.com> wrote:

 Correct. But if you overload it, you can change the return type - but be
 aware that will create more than one entry for cmp in the vtbl[].

Then, take a look at this: class Foo { float cmp() { ... } } void process(Object a, Object b) { if (a < b) ... else ... } int main() { process(new Foo, new Foo); } Now, which version of cmp() will be used in process()?
Aug 21 2002
parent reply Pavel Minayev <evilone omen.ru> writes:
On Wed, 21 Aug 2002 01:21:43 -0700 "Walter" <walter digitalmars.com> wrote:

 The
     int Foo.cmp(Object o);
 version will be used. Since process() doesn't know about NaN's anyway,
 you'll need to overload int cmp(Object o); to perhaps throw an exception on
 a NaN, and then write a float cmp(MyFloat o) to handle NaN's.

process() doesn't need to know anything of NaNs - but it relies on the fact that correct comparison is performed regardless of actual types of objects. Maybe it would really be better to make cmp() always return float? I don't think it would add any significant slowdown, but the feature would then be consistent...
Aug 21 2002
parent reply "Martin M. Pedersen" <mmp www.moeller-pedersen.dk> writes:
Hi,

"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374899500592593 news.digitalmars.com...
 Maybe it would really be better to make cmp() always return float?
 I don't think it would add any significant slowdown, but the feature
 would then be consistent...

If floating point isn't supported by hardware, it would cause a major performance hit. Regards, Martin M. Pedersen
Aug 21 2002
parent reply Pavel Minayev <evilone omen.ru> writes:
On Wed=2C 21 Aug 2002 22=3A11=3A45 +0100 =22Martin M=2E Pedersen=22 
=3Cmmp=40www=2Emoeller-pedersen=2Edk=3E wrote=3A

=3E If floating point isn't supported by hardware=2C it would cause a major
=3E performance hit=2E

Then=2C let's define a standard =22fp-comparison=22 interface in object=2Ed=3A

=09interface CompareFP
=09{
=09=09float cmp=28=29=3B
=09}

Now process=28=29 would be=3A

=09process=28CompareFP a=2C CompareFP b=29
=09{
=09=09=2E=2E=2E
=09}

And all problems are gone=2E
Aug 21 2002
parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
Have cmp() return an enum:

enum CmpResult
{
    LessThan = -1,
    EqualTo = 0,
    GreaterThan = 1,
    Undefined = 1<<31,
}

So this will work:

float a = sqrt(-1); // generate NaN
float b = 1;
if (a.cmp(b) != 0)
    printf("they're different\n");

Using the old cmpresult < 0 and cmpresult > 0 checks will mistakenly think
that NaN comparisons are less than, but that shouldn't be a big problem.
And we can leave cmp() defined to return int.

Sean

"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374900566370602 news.digitalmars.com...
On Wed, 21 Aug 2002 22:11:45 +0100 "Martin M. Pedersen"
<mmp www.moeller-pedersen.dk> wrote:

 If floating point isn't supported by hardware, it would cause a major
 performance hit.

Then, let's define a standard "fp-comparison" interface in object.d: interface CompareFP { float cmp(); } Now process() would be: process(CompareFP a, CompareFP b) { ... } And all problems are gone.
Aug 22 2002
next sibling parent reply Pavel Minayev <evilone omen.ru> writes:
On Thu, 22 Aug 2002 10:26:54 -0700 "Sean L. Palmer" <seanpalmer earthlink.net> 
wrote:

 Have cmp() return an enum:
 
 enum CmpResult
 {
     LessThan = -1,
     EqualTo = 0,
     GreaterThan = 1,
     Undefined = 1<<31,
 }

A nice idea.
Aug 22 2002
parent "Martin M. Pedersen" <mmp www.moeller-pedersen.dk> writes:
Hi,

"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374909708268634 news.digitalmars.com...
 enum CmpResult


I agree. Regards, Martin M. Pedersen
Aug 22 2002
prev sibling parent "Walter" <walter digitalmars.com> writes:
"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:ak36cs$23d7$1 digitaldaemon.com...
 Have cmp() return an enum:

 enum CmpResult
 {
     LessThan = -1,
     EqualTo = 0,
     GreaterThan = 1,
     Undefined = 1<<31,
 }

 So this will work:

 float a = sqrt(-1); // generate NaN
 float b = 1;
 if (a.cmp(b) != 0)
     printf("they're different\n");

 Using the old cmpresult < 0 and cmpresult > 0 checks will mistakenly think
 that NaN comparisons are less than, but that shouldn't be a big problem.
 And we can leave cmp() defined to return int.

The behavior of < and > is defined for NaNs, so there would have two be two comparisons for every cmp. The CPU handles this by setting the P flag for NaN comparisons, but that isn't accessible to functions.
Aug 23 2002
prev sibling parent reply Burton Radons <loth users.sourceforge.net> writes:
Walter wrote:

 "Burton Radons" <loth users.sourceforge.net> wrote in message
 news:3D5F0476.1060203 users.sourceforge.net...
 
Walter, could you back one of us up here, please?

I think it will work right if: a op b is rewritten as: a.cmp(b) op 0 For the nan cases, the cmp function can return nan's.

I don't have a problem with making this change, but I think it should be consistent or it'll cause more confusion than enlightenment. Always returning float from cmp is actually helpful, since it can then be used if eq isn't provided, which it almost universally won't be, and it handles "long - long" properly. Better yet would be to remove eq and see how many complaints there are.
Aug 21 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Burton Radons" <loth users.sourceforge.net> wrote in message
news:3D63BB45.3040706 users.sourceforge.net...
 I don't have a problem with making this change, but I think it should be
 consistent or it'll cause more confusion than enlightenment.  Always
 returning float from cmp is actually helpful, since it can then be used
 if eq isn't provided, which it almost universally won't be, and it
 handles "long - long" properly.  Better yet would be to remove eq and
 see how many complaints there are.

Always returning float has a problem for embedded systems which may want to use an integer-only subset of D, and also it would be a problem in general for machines which have arbitrarilly slow floating point. The reason for a separate eq from cmp is that for many objects there is no concept of "less than", although there is a concept for "equals".
Aug 21 2002
parent reply Burton Radons <loth users.sourceforge.net> writes:
Walter wrote:

 "Burton Radons" <loth users.sourceforge.net> wrote in message
 news:3D63BB45.3040706 users.sourceforge.net...
 
I don't have a problem with making this change, but I think it should be
consistent or it'll cause more confusion than enlightenment.  Always
returning float from cmp is actually helpful, since it can then be used
if eq isn't provided, which it almost universally won't be, and it
handles "long - long" properly.  Better yet would be to remove eq and
see how many complaints there are.

Always returning float has a problem for embedded systems which may want to use an integer-only subset of D, and also it would be a problem in general for machines which have arbitrarilly slow floating point.

Uh, okay, but if float is supported in comparison then float will be used practically everywhere, and the embedded problem is not eased at all. Besides which, this is poppycock. Comparison against zero is a trivial operation whether you have hardware support or not. Zero: v == 0 Negative: v & 0x80000000 NaN: (v & 0x7FFF0000) == 0x7FFF0000 && (v & 0xFFFF) Positive: none of the above I'm sure that bit twiddlers could bring that down to fewer operations, but it's clearly not of any consequence.
 The reason for a separate eq from cmp is that for many objects there is no
 concept of "less than", although there is a concept for "equals".

In which case they'll only return 0 or float.nan.
Aug 21 2002
parent "Walter" <walter digitalmars.com> writes:
"Burton Radons" <loth users.sourceforge.net> wrote in message
news:3D640B7D.5000603 users.sourceforge.net...
 Always returning float has a problem for embedded systems which may want


 use an integer-only subset of D, and also it would be a problem in


 for machines which have arbitrarilly slow floating point.

used practically everywhere, and the embedded problem is not eased at all.

Float is only necessary for supporting NaN comparisons. Other comparisons most likely will stick to simple int returns of <0, 0, or >0.
 Besides which, this is poppycock.  Comparison against zero is a trivial
 operation whether you have hardware support or not.

 Zero: v == 0
 Negative: v & 0x80000000
 NaN: (v & 0x7FFF0000) == 0x7FFF0000 && (v & 0xFFFF)
 Positive: none of the above
 I'm sure that bit twiddlers could bring that down to fewer operations,
 but it's clearly not of any consequence.

I disagree, in loops especially it can be extremely sensitive to comparison time.
Aug 23 2002
prev sibling parent Pavel Minayev <evilone omen.ru> writes:
This scored most:

 5) 'operator (a - b)' or 'operator (this - b)'.  (my vote: +0)  If I had 
 to put in any new syntax I would prefer it to be this one.
 
     static Vector operator (a - b) (Vector a, Vector b);


And this did:
 1) Operators are normal, possibly virtual methods in classes, normal 
 nonvirtual methods in structs (My vote: +1).
 
     Vector add (Vector b);


Now, the question is, what is "static" doing in the syntax? =)
Aug 17 2002
prev sibling next sibling parent reply "anderson" <anderson firestar.com.au> writes:
One thing I dissagree with is the way you conducted this survay. Next time
keep your opinions in a separate email please. Explain what you mean as much
as you want, but don't optionate it. Otherwise you may effect the results of
your replies.

I'm not trying to flame you, I'm just pointing this out for next time.
Aug 17 2002
parent "anderson" <anderson firestar.com.au> writes:
Whoops

"anderson" <anderson firestar.com.au> wrote in message
news:ajkvgl$h0k$1 digitaldaemon.com...
 One thing I dissagree with, is the way you conducted this survay. Next

 keep your opinions in a separate email please. Explain what you mean as

 as you want, but don't put opinions in it. Otherwise you may effect the

 of your replies.

 I'm not trying to flame you, I'm just pointing this out for next time.

Aug 17 2002
prev sibling next sibling parent reply Toyotomi <io219 attbi.com> writes:
On Thu, 08 Aug 2002 06:57:04 -0700, Burton Radons
<loth users.sourceforge.net> wrote:

I've accidentally implemented operator overloading in my port.  It was 
kind of incidental to other work, so I thought "what the hell" and threw 
it in.  But this brings up the whole issue of syntax, and I think that 
should be voted on to specify the syntax on my side and to influence 
Walter when he decides to do this topic.

I'm scared of voting... it's too much like a committee...
Aug 21 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Toyotomi" <io219 attbi.com> wrote in message
news:oll7mu4nat45gi1gjfvslh7mriv0b3jer7 4ax.com...
 I'm scared of voting... it's too much like a committee...

I think democratically designed languages tend to be failures <g>. Nevertheless, ignoring feedback from users is equally perilous. These kinds of discussions help me to understand what things are important and what are not.
Aug 21 2002
parent Toyotomi <io219 attbi.com> writes:
On Wed, 21 Aug 2002 14:27:33 -0700, "Walter" <walter digitalmars.com>
wrote:

"Toyotomi" <io219 attbi.com> wrote in message
news:oll7mu4nat45gi1gjfvslh7mriv0b3jer7 4ax.com...
 I'm scared of voting... it's too much like a committee...

I think democratically designed languages tend to be failures <g>. Nevertheless, ignoring feedback from users is equally perilous. These kinds of discussions help me to understand what things are important and what are not.

Glad you see the first bit that way. Ignoring is a bit _less_ perilous in my opinion though. ;-p I think I can see I don't have too much to fear. Thanks.
Aug 21 2002
prev sibling parent reply "Carlos Santander B." <carlos8294 msn.com> writes:
Should we vote this again? I mean, there're some complaining about how
overloaded operators should work...

"Burton Radons" <loth users.sourceforge.net> wrote in message
news:3D5278B0.1000508 users.sourceforge.net...
| I've accidentally implemented operator overloading in my port.  It was
| kind of incidental to other work, so I thought "what the hell" and threw
| it in.  But this brings up the whole issue of syntax, and I think that
| should be voted on to specify the syntax on my side and to influence
| Walter when he decides to do this topic.
|
| I'd like Apache-style voting to be used, where the voting is either -1,
| -0, 0, +0, or +1 for any option, which is a good bellweather of how
| people think about something.
|
| First off, the naming scheme:
|
| 1) "add", "mul", "div", etc.  (my vote: +1)
|
|      Vector mul (Vector b);
|      Vector div (Vector b);
|
| 2) "op_add", "op_mul", "op_div", etc.  (my vote: +1)
|
|      Vector op_sub (Vector b);
|      Vector op_mod (Vector b);
|
| 3) "operator +".  (my vote: -1)  My vote is because I find this syntax
| confusing in C++, particularly with its wide expressiveness, and I
| admire any syntax which doesn't require a change to tools, as the above
| don't.
|
|      Vector operator + (Vector b);
|
| 4) 'operator "+"'.  (my vote: -0)  For some reason I find this less
| visually disconcerting.
|
|      Vector operator "*" (Vector b);
|
| 5) 'operator (a - b)' or 'operator (this - b)'.  (my vote: +0)  If I had
| to put in any new syntax I would prefer it to be this one.
|
|      static Vector operator (a - b) (Vector a, Vector b);
|
| Now, where overloaded operators are defined:
|
| 1) Operators are normal, possibly virtual methods in classes, normal
| nonvirtual methods in structs (My vote: +1).
|
|      Vector add (Vector b);
|
| 2) Overloaded operators are always static methods with both left and
| right arguments defined (My vote: 0).
|
|      static Vector add (Vector a, Vector b);
|
| 3) Overloaded operators are global functions, using both arguments (My
| vote: -1).
|
|      Vector add (Vector a, Vector b);
|
| 4) Operator overloading shouldn't be put in (My vote: -1).
|
| Now, reverse operator handling, where you want the right-side expression
| to handle the evaluation, such as with the form "int * Vector":
|
| 1) A second set of potential functions (My vote: +1).
|
| 2) Automatic reorganization of the expression.  This makes assumptions
| about what the operators do and can't handle "1 / Vector" (My vote: -1).
|   For example, "1-A" could become "-A+1".
|
| Now for the operations covered.  Please be temperate with your votes -
| operations can be added later, but they can't be removed as easily.
|
| 1) a + b, a - b, a * b, a / b, a % b, -a, +a.  (my vote: +1)
|
| 2) a & b, a | b, a ^ b, ~a, !a.  (my vote: +1)
|
| 3) a++, a--, --a, ++a.  (my vote: 0)
|
| 4) a = b.  (my vote: 0)
|
| 5) a << b, a >> b, a >>> b.  (my vote: +1)
|
| 6) a += b, a -= b, a *= b, a %= b, etc.  (my vote: -1)
|
| 7) new, delete.  (my vote: -0)
|
| 8) a || b, a && b.  (my vote: -1)
|
| 9) explicit a >= b, a > b, a <= b, a < b.  (my vote: -1)
|
| 10) a [b].  (my vote: +1)
|
| 10a) a [b] = c.  (my vote: +0)
|
| 11) a [b .. c].  (my vote: +1)
|
| 12) &a, *a.  (my vote: -1)
|
| 13) a.b, a.b = c.  Retrieve and assign property.  (my vote: +1)  Note
| that this won't allow just anything in b.
|
| 13a) a . b, where b can be any type.  (my vote: -1)
|
| 14) a ? b : c.  (my vote: -1)
|
| 15) a === b, a !== b.  (my vote: 0)
|
| 16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my vote: 0)
| IMO this is an eq/cmp combination issue.
|
| 17) a in b.  (my vote: +1)
|
| 18) cast (b) a.  (my vote: -0)  I haven't had any good experiences with
| cast overloading in C++.
|
| 19) (a, b).  (my vote: -1)
|
| And miscellaneous:
|
| 1) Operator overloading should be allowed on basic types as global
| functions.  (my vote: -1)
|
|      int operator "a - b" (int a, int b);
|
| 2) Definition of new operators is allowed.  I'll ignore this one if it
| goes positive.  (my vote: -1)
|
|      Vector operator (this dot b) (Vector b);
|
| 2a) Setting precedence of new operators is allowed.  I'll ignore this
| one if it goes positive.  (my vote: -1)
|
|      operator (a dot b) above (a >= b) below (a * b);
|
| I think that's about it.
|


---

Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.538 / Virus Database: 333 - Release Date: 2003-11-10
Nov 13 2003
next sibling parent reply davepermen <davepermen_member pathlink.com> writes:
1) "add", "mul", "div", etc.
-1
it can be used for own functions very nice, wich should NOT be operators then.

2) "op_add", "op_mul", "op_div", etc.  (my vote: +1)
-0
less chance to get used as normal func wich should NOT be operator.. but opAdd
would be the D way then. doesn't mather.. i don't like it

3) "operator +".
+1
definitely best. its an unambiguous name, not to use for anything else.. except
possibly +(a,b) or operator+(a,b).. but the issues of 1) and 2) are not there.

4) 'operator "+"'.
-1
its not an operator on a string token

5) 'operator (a - b)' or 'operator (this - b)'.
0
never seen it before.. and directly the suggested way, -1, but the idea is
something we could think about..
Vector operator(Vector a - Vector b) {
return sub(a,b);
}
_could_ be a nice way..



next:


1) Operators are normal, possibly virtual methods in classes, normal nonvirtual
methods in structs
+1
they _can_ be
2) Overloaded operators are always static methods with both left and right
arguments defined
-1
not always.
3) Overloaded operators are global functions, using both arguments 
+1
definitely way to go. if you know oo, if you know encapsulation, you have to
allow that. if not, read more on www.cuj.com (thats the link?).
its the only way to make operators extendable, just "adding another layer". the
whole very dynamic stream concept of c++ would have never worked without that.
and there's more.. (end of text)
4) Operator overloading shouldn't be put in
-2
it definitely has to be in.



next
1) A second set of potential functions
+0
acceptable, the way c++ did it, too
2) Automatic reorganization of the expression.
-1
this defeats the way to define them with new behaviour.

and a new one:
3) specify by some token.. like
Vector operator+ (Vector a,Vector b) reversible {
return add(a,b);
}
(reversible isn't the mathematical term.. but i'm too tierd currently to use my
brain for remembering that term..)
oh, and..
+1
it saves the additional typing. why not?


next



1) a + b, a - b, a * b, a / b, a % b, -a, +a.
+1
2) a & b, a | b, a ^ b, ~a, !a.
!a doesn't fit in this list as the rest are binary ops.. for binary ops:
+1
for !
0
3) a++, a--, --a, ++a.
for --a and ++a, yes. a++,a-- should be autoimplemented.. its just a changing of
the order.. but they can be useful for iterator thingies..
+0
4) a = b.  (my vote: 0)
+0
i think yes.
but as a binary operator, not the way c++ does with possibility of a
constructor, or an operator AType()
void operator = (TypeA a,TypeB b) {
a.set(b);
}
5) a << b, a >> b, a >>> b.  (my vote: +1)
+1
6) a += b, a -= b, a *= b, a %= b, etc.
if we have them, we don't need 1) actually..
+0
7) new, delete.
+1
if the way they are done now.. they can be useful.
8) a || b, a && b.
-1
9) explicit a >= b, a > b, a <= b, a < b
0
i don't need them. but i've seen people who'd like to have them, and for
reasons..
10) a[b].
+1
10a) a[b] = c.
uhm?
11) a[b..c]
+1
12) &a, *a.
-1
13) a.b, a.b = c.
-1 we have properties for such things
14) a ? b : c.  (my vote: -1)
-1
15) a === b, a !== b.
-1
this is defined to be the comparison if its the identical object. not
overloadable.
16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my vote: 0)
hm?
-0
17) a in b.
+1
18) cast (b) a.
hm.. hm...
0
19) (a, b).
hm..
-1


next
1) Operator overloading should be allowed on basic types as global functions.
-1
2) Definition of new operators is allowed.  I'll ignore this one if it goes
positive.
-1
2a) Setting precedence of new operators is allowed.  I'll ignore this one if it
goes positive.
+0
actually this could get interesting for the standard operators, too.. but not
that syntax, and it can be dangerous.. but the idea still makes a lot of sence..




(so, final statement:D)

binary operators should be functions, not member functions or anything (but
could be, and should be possible to be).

reasoning:

Vector operator*(Vector a,Quaternion q);

that belongs to who? to class Vector? or class Quaternion?. to NONE. its a
mathermatical function on BOTH. it is linking them together with some operation.
but it does not belong to any of those. thus, it should not be member of any.
this helps encapsulation. operator* in this case doesn't have direct access to
Vector and Quaternion. (they both would be structs with public members in THIS
case, but anyways). this means implementation can change, operator doesn't
bother about it.
else, it would say belong to Vector. it would not have the possibility to access
Quaternion. but it could access Vector. this is an unfair situation, and doesn't
make sence.


unary operators should be members. but of course, they don't have to.. reasoning
is, they only belong to one variable of one type, so that fits well..
class Vector {
Vector operator-() {
return negated(this);
}
}




the great thing about having them as global functions is the ability to ADD them
afterwards. you get a library, say like a D3DX library. they have nice functions
like D3DXMatrixMultiply(D3DXVector* out,D3DXMatrix* m,D3DXVector* in); or
similar.

all you need to do then is write..
D3DXVector operator*(D3DXMatrix m,D3DXVector v) {
D3DXVector ret;
D3DXMatrixMultiply(&ret,&m,&v);
return ret;
}

and you added the functionality. without touching the D3DX library at all.



same for say streams..
Stream operator<<(Stream s,Type obj) {
return s<<obj.foo<<obj.bla<<obj.bar;
}


this adds a lot of functionality. a lot of freedom. and a lot of savety. it
eases our tasks as well by much..







oh, and you forgot operator() :D
Nov 14 2003
parent reply "Sean L. Palmer" <palmer.sean verizon.net> writes:
"davepermen" <davepermen_member pathlink.com> wrote in message
news:bp2hml$1dlq$1 digitaldaemon.com...
 3) specify by some token.. like
 Vector operator+ (Vector a,Vector b) reversible {
 return add(a,b);
 }
 (reversible isn't the mathematical term.. but i'm too tierd currently to

 brain for remembering that term..)

It's called commutativity
 1) a + b, a - b, a * b, a / b, a % b, -a, +a.
 +1
 2) a & b, a | b, a ^ b, ~a, !a.
 !a doesn't fit in this list as the rest are binary ops.. for binary ops:
 +1
 for !
 0

You're mistaken. Look again.
 3) a++, a--, --a, ++a.
 for --a and ++a, yes. a++,a-- should be autoimplemented.. its just a

 the order.. but they can be useful for iterator thingies..
 +0
 4) a = b.  (my vote: 0)
 +0
 i think yes.
 but as a binary operator, not the way c++ does with possibility of a
 constructor, or an operator AType()
 void operator = (TypeA a,TypeB b) {
 a.set(b);
 }

You are right, construction and destruction do not make sense most of the time, it is conversion or production that gives us 99% of our values. Let's focus on that. Assignment is pretty fundamental to procedural languages. Assigning one value to a variable of another type is an implicit conversion, and those are really good to be able to define simply, OUTSIDE of the class declaration, because otherwise you get into the C++ mess of user-defined conversions which are exactly the same thing as constructors, if you really think about it. The copy constructor could likewise be eliminated, and becomes a special case of assigning a value to an lvalue of its own type, in other words same as the basic assignment operator.
 5) a << b, a >> b, a >>> b.  (my vote: +1)
 +1
 6) a += b, a -= b, a *= b, a %= b, etc.
 if we have them, we don't need 1) actually..
 +0
 7) new, delete.
 +1
 if the way they are done now.. they can be useful.

I've never really liked new and delete. I would love to get rid of them and just use factory / demolition functions (assignments to/from void work for this purpose).
 10) a[b].
 +1
 10a) a[b] = c.
 uhm?

array store (array used as lvalue)
 12) &a, *a.
 -1

The C++ purpose for these being overloadable is to provide and dereference pointer types. &a is pretty much the equivalent of saying a.begin(), null is almost equivalent to a.end(). If you use them, you give up the ability to take the address of a variable, you "wrap" that type's pointer capability.
 1) Operator overloading should be allowed on basic types as global

 -1

Why not? ++float float >> 1 These are good examples of why I think it *should* be allowed. The language designers "forgot" those operations, creating little pitfalls and minefields in template authoring.
 2) Definition of new operators is allowed.  I'll ignore this one if it

 positive.
 -1

I hate you all!! There are not nearly enough operators to go around. Sean
Nov 21 2003
parent reply davepermen <davepermen_member pathlink.com> writes:
quoting {
 2) a & b, a | b, a ^ b, ~a, !a.
 !a doesn't fit in this list as the rest are binary ops.. for binary ops:
 +1
 for !
 0

You're mistaken. Look again. } first: i made a typo. but my statement is correct. !a is no binary op. its an unary op:D (read up yourself). what i ment is, ! is not a bitwise op. the others are. a&b ands all bits. a|b ors all bits, a^b xors all bits, ~a inverts all bits, but !a returns a boolean, and only checks if all bits are zero, or not, to return that boolean. ! belongs to &&,||, a possible ^^ (hehe:D), etc.. it is a logical op. not a bitwise op. i just checked the docu's, and it still is. as in c++.
Nov 22 2003
parent reply "Sean L. Palmer" <palmer.sean verizon.net> writes:
Doh!  I thought you meant binary as in "not unary", instead of what you
really meant, which was "not logical".  ;)

Sean


"davepermen" <davepermen_member pathlink.com> wrote in message
news:bpnsck$2r4l$1 digitaldaemon.com...
 quoting {
 2) a & b, a | b, a ^ b, ~a, !a.
 !a doesn't fit in this list as the rest are binary ops.. for binary ops:
 +1
 for !
 0

You're mistaken. Look again. } first: i made a typo. but my statement is correct. !a is no binary op. its

 unary op:D (read up yourself).

 what i ment is, ! is not a bitwise op. the others are. a&b ands all bits.

 ors all bits, a^b xors all bits, ~a inverts all bits, but !a returns a

 and only checks if all bits are zero, or not, to return that boolean.

 ! belongs to &&,||, a possible ^^ (hehe:D), etc.. it is a logical op. not

 bitwise op. i just checked the docu's, and it still is. as in c++.

Nov 24 2003
parent davepermen <davepermen_member pathlink.com> writes:
hehe sorry..
:D

In article <bpsljg$hlc$1 digitaldaemon.com>, Sean L. Palmer says...
Doh!  I thought you meant binary as in "not unary", instead of what you
really meant, which was "not logical".  ;)

Sean

Nov 24 2003
prev sibling parent reply "Matthew Wilson" <matthew-hat -stlsoft-dot.-org> writes:
I don't care too much about what they're called (although I don't like the
current naming conventions much).

What's really important is that operators be not always bound to instances,
i.e. we can (and should) declare binary operators as free functions, and we
should have the right to do so with unary operators.

I'm not sure it's necessary to vote on this, because I think this will be
change that will be forced on D (i.e. on Walter) at some point, as the
problems associated with the current approach become too great to ignore.

IMO, if that change does not happen, D will founder

"Carlos Santander B." <carlos8294 msn.com> wrote in message
news:bp1fs0$2oat$1 digitaldaemon.com...
 Should we vote this again? I mean, there're some complaining about how
 overloaded operators should work...

 "Burton Radons" <loth users.sourceforge.net> wrote in message
 news:3D5278B0.1000508 users.sourceforge.net...
 | I've accidentally implemented operator overloading in my port.  It was
 | kind of incidental to other work, so I thought "what the hell" and threw
 | it in.  But this brings up the whole issue of syntax, and I think that
 | should be voted on to specify the syntax on my side and to influence
 | Walter when he decides to do this topic.
 |
 | I'd like Apache-style voting to be used, where the voting is either -1,
 | -0, 0, +0, or +1 for any option, which is a good bellweather of how
 | people think about something.
 |
 | First off, the naming scheme:
 |
 | 1) "add", "mul", "div", etc.  (my vote: +1)
 |
 |      Vector mul (Vector b);
 |      Vector div (Vector b);
 |
 | 2) "op_add", "op_mul", "op_div", etc.  (my vote: +1)
 |
 |      Vector op_sub (Vector b);
 |      Vector op_mod (Vector b);
 |
 | 3) "operator +".  (my vote: -1)  My vote is because I find this syntax
 | confusing in C++, particularly with its wide expressiveness, and I
 | admire any syntax which doesn't require a change to tools, as the above
 | don't.
 |
 |      Vector operator + (Vector b);
 |
 | 4) 'operator "+"'.  (my vote: -0)  For some reason I find this less
 | visually disconcerting.
 |
 |      Vector operator "*" (Vector b);
 |
 | 5) 'operator (a - b)' or 'operator (this - b)'.  (my vote: +0)  If I had
 | to put in any new syntax I would prefer it to be this one.
 |
 |      static Vector operator (a - b) (Vector a, Vector b);
 |
 | Now, where overloaded operators are defined:
 |
 | 1) Operators are normal, possibly virtual methods in classes, normal
 | nonvirtual methods in structs (My vote: +1).
 |
 |      Vector add (Vector b);
 |
 | 2) Overloaded operators are always static methods with both left and
 | right arguments defined (My vote: 0).
 |
 |      static Vector add (Vector a, Vector b);
 |
 | 3) Overloaded operators are global functions, using both arguments (My
 | vote: -1).
 |
 |      Vector add (Vector a, Vector b);
 |
 | 4) Operator overloading shouldn't be put in (My vote: -1).
 |
 | Now, reverse operator handling, where you want the right-side expression
 | to handle the evaluation, such as with the form "int * Vector":
 |
 | 1) A second set of potential functions (My vote: +1).
 |
 | 2) Automatic reorganization of the expression.  This makes assumptions
 | about what the operators do and can't handle "1 / Vector" (My vote: -1).
 |   For example, "1-A" could become "-A+1".
 |
 | Now for the operations covered.  Please be temperate with your votes -
 | operations can be added later, but they can't be removed as easily.
 |
 | 1) a + b, a - b, a * b, a / b, a % b, -a, +a.  (my vote: +1)
 |
 | 2) a & b, a | b, a ^ b, ~a, !a.  (my vote: +1)
 |
 | 3) a++, a--, --a, ++a.  (my vote: 0)
 |
 | 4) a = b.  (my vote: 0)
 |
 | 5) a << b, a >> b, a >>> b.  (my vote: +1)
 |
 | 6) a += b, a -= b, a *= b, a %= b, etc.  (my vote: -1)
 |
 | 7) new, delete.  (my vote: -0)
 |
 | 8) a || b, a && b.  (my vote: -1)
 |
 | 9) explicit a >= b, a > b, a <= b, a < b.  (my vote: -1)
 |
 | 10) a [b].  (my vote: +1)
 |
 | 10a) a [b] = c.  (my vote: +0)
 |
 | 11) a [b .. c].  (my vote: +1)
 |
 | 12) &a, *a.  (my vote: -1)
 |
 | 13) a.b, a.b = c.  Retrieve and assign property.  (my vote: +1)  Note
 | that this won't allow just anything in b.
 |
 | 13a) a . b, where b can be any type.  (my vote: -1)
 |
 | 14) a ? b : c.  (my vote: -1)
 |
 | 15) a === b, a !== b.  (my vote: 0)
 |
 | 16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my vote: 0)
 | IMO this is an eq/cmp combination issue.
 |
 | 17) a in b.  (my vote: +1)
 |
 | 18) cast (b) a.  (my vote: -0)  I haven't had any good experiences with
 | cast overloading in C++.
 |
 | 19) (a, b).  (my vote: -1)
 |
 | And miscellaneous:
 |
 | 1) Operator overloading should be allowed on basic types as global
 | functions.  (my vote: -1)
 |
 |      int operator "a - b" (int a, int b);
 |
 | 2) Definition of new operators is allowed.  I'll ignore this one if it
 | goes positive.  (my vote: -1)
 |
 |      Vector operator (this dot b) (Vector b);
 |
 | 2a) Setting precedence of new operators is allowed.  I'll ignore this
 | one if it goes positive.  (my vote: -1)
 |
 |      operator (a dot b) above (a >= b) below (a * b);
 |
 | I think that's about it.
 |


 ---

 Checked by AVG anti-virus system (http://www.grisoft.com).
 Version: 6.0.538 / Virus Database: 333 - Release Date: 2003-11-10

Nov 14 2003
parent reply "Charles Sanders" <sanders-consulting comcast.net> writes:
 What's really important is that operators be not always bound to

Could you tell me what you mean here, with an example ?
 I'm not sure it's necessary to vote on this, because I think this will be
 change that will be forced on D

Yea but I personally would like this ASAP, i dont like the current inconsistent convention and am hoping each release will fix it. C "Matthew Wilson" <matthew-hat -stlsoft-dot.-org> wrote in message news:bp3dfi$2qs9$1 digitaldaemon.com...
 I don't care too much about what they're called (although I don't like the
 current naming conventions much).

 What's really important is that operators be not always bound to

 i.e. we can (and should) declare binary operators as free functions, and

 should have the right to do so with unary operators.

 I'm not sure it's necessary to vote on this, because I think this will be
 change that will be forced on D (i.e. on Walter) at some point, as the
 problems associated with the current approach become too great to ignore.

 IMO, if that change does not happen, D will founder

 "Carlos Santander B." <carlos8294 msn.com> wrote in message
 news:bp1fs0$2oat$1 digitaldaemon.com...
 Should we vote this again? I mean, there're some complaining about how
 overloaded operators should work...

 "Burton Radons" <loth users.sourceforge.net> wrote in message
 news:3D5278B0.1000508 users.sourceforge.net...
 | I've accidentally implemented operator overloading in my port.  It was
 | kind of incidental to other work, so I thought "what the hell" and


 | it in.  But this brings up the whole issue of syntax, and I think that
 | should be voted on to specify the syntax on my side and to influence
 | Walter when he decides to do this topic.
 |
 | I'd like Apache-style voting to be used, where the voting is


 | -0, 0, +0, or +1 for any option, which is a good bellweather of how
 | people think about something.
 |
 | First off, the naming scheme:
 |
 | 1) "add", "mul", "div", etc.  (my vote: +1)
 |
 |      Vector mul (Vector b);
 |      Vector div (Vector b);
 |
 | 2) "op_add", "op_mul", "op_div", etc.  (my vote: +1)
 |
 |      Vector op_sub (Vector b);
 |      Vector op_mod (Vector b);
 |
 | 3) "operator +".  (my vote: -1)  My vote is because I find this syntax
 | confusing in C++, particularly with its wide expressiveness, and I
 | admire any syntax which doesn't require a change to tools, as the


 | don't.
 |
 |      Vector operator + (Vector b);
 |
 | 4) 'operator "+"'.  (my vote: -0)  For some reason I find this less
 | visually disconcerting.
 |
 |      Vector operator "*" (Vector b);
 |
 | 5) 'operator (a - b)' or 'operator (this - b)'.  (my vote: +0)  If I


 | to put in any new syntax I would prefer it to be this one.
 |
 |      static Vector operator (a - b) (Vector a, Vector b);
 |
 | Now, where overloaded operators are defined:
 |
 | 1) Operators are normal, possibly virtual methods in classes, normal
 | nonvirtual methods in structs (My vote: +1).
 |
 |      Vector add (Vector b);
 |
 | 2) Overloaded operators are always static methods with both left and
 | right arguments defined (My vote: 0).
 |
 |      static Vector add (Vector a, Vector b);
 |
 | 3) Overloaded operators are global functions, using both arguments (My
 | vote: -1).
 |
 |      Vector add (Vector a, Vector b);
 |
 | 4) Operator overloading shouldn't be put in (My vote: -1).
 |
 | Now, reverse operator handling, where you want the right-side


 | to handle the evaluation, such as with the form "int * Vector":
 |
 | 1) A second set of potential functions (My vote: +1).
 |
 | 2) Automatic reorganization of the expression.  This makes assumptions
 | about what the operators do and can't handle "1 / Vector" (My


 |   For example, "1-A" could become "-A+1".
 |
 | Now for the operations covered.  Please be temperate with your votes -
 | operations can be added later, but they can't be removed as easily.
 |
 | 1) a + b, a - b, a * b, a / b, a % b, -a, +a.  (my vote: +1)
 |
 | 2) a & b, a | b, a ^ b, ~a, !a.  (my vote: +1)
 |
 | 3) a++, a--, --a, ++a.  (my vote: 0)
 |
 | 4) a = b.  (my vote: 0)
 |
 | 5) a << b, a >> b, a >>> b.  (my vote: +1)
 |
 | 6) a += b, a -= b, a *= b, a %= b, etc.  (my vote: -1)
 |
 | 7) new, delete.  (my vote: -0)
 |
 | 8) a || b, a && b.  (my vote: -1)
 |
 | 9) explicit a >= b, a > b, a <= b, a < b.  (my vote: -1)
 |
 | 10) a [b].  (my vote: +1)
 |
 | 10a) a [b] = c.  (my vote: +0)
 |
 | 11) a [b .. c].  (my vote: +1)
 |
 | 12) &a, *a.  (my vote: -1)
 |
 | 13) a.b, a.b = c.  Retrieve and assign property.  (my vote: +1)  Note
 | that this won't allow just anything in b.
 |
 | 13a) a . b, where b can be any type.  (my vote: -1)
 |
 | 14) a ? b : c.  (my vote: -1)
 |
 | 15) a === b, a !== b.  (my vote: 0)
 |
 | 16) a !<> b, a <> b, a !> b, a !< b, a !<= b, a !>= b.  (my vote: 0)
 | IMO this is an eq/cmp combination issue.
 |
 | 17) a in b.  (my vote: +1)
 |
 | 18) cast (b) a.  (my vote: -0)  I haven't had any good experiences


 | cast overloading in C++.
 |
 | 19) (a, b).  (my vote: -1)
 |
 | And miscellaneous:
 |
 | 1) Operator overloading should be allowed on basic types as global
 | functions.  (my vote: -1)
 |
 |      int operator "a - b" (int a, int b);
 |
 | 2) Definition of new operators is allowed.  I'll ignore this one if it
 | goes positive.  (my vote: -1)
 |
 |      Vector operator (this dot b) (Vector b);
 |
 | 2a) Setting precedence of new operators is allowed.  I'll ignore this
 | one if it goes positive.  (my vote: -1)
 |
 |      operator (a dot b) above (a >= b) below (a * b);
 |
 | I think that's about it.
 |


 ---

 Checked by AVG anti-virus system (http://www.grisoft.com).
 Version: 6.0.538 / Virus Database: 333 - Release Date: 2003-11-10


Nov 14 2003
parent "Matthew Wilson" <matthew-hat -stlsoft-dot.-org> writes:
"Charles Sanders" <sanders-consulting comcast.net> wrote in message
news:bp40ik$plv$1 digitaldaemon.com...
 What's really important is that operators be not always bound to

Could you tell me what you mean here, with an example ?

1. Operators as instances (C++ syntax, I'm afraid): class X { X operator +(X const &rhs); // "this" is the lhs }; 2. Free functions: class X {} X operator +(X const &lhs, X const &rhs);
 I'm not sure it's necessary to vote on this, because I think this will


 change that will be forced on D

Yea but I personally would like this ASAP, i dont like the current inconsistent convention and am hoping each release will fix it.

Me too, but there seems much resistance on Walter's part. I can see that it's probably a big job. It will happen eventually, though, I have no doubt
Nov 14 2003