February 12, 2002
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3C6979F9.D014E2C8@deming-os.org...

> True, but that is only for things that are reasonably ordered.  Some
things
> may have a property of equality/inequality but not ordering.  In that
case,
> you want to supply == and != but not < > <= >=

That's why I suggest the special "operator cmp".


February 12, 2002
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3C697B1B.1B10E356@deming-os.org...

> You could simply define that for built-in types :+: is exactly equivalent
to
> +    Or am I missing the point here?

What about the ":+-*/:" operator, then? =)




February 12, 2002
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3C697B1B.1B10E356@deming-os.org...
> Walter wrote:
> > The trouble is you couldn't write a template that could be instantiated
for
> > both builtin types and user defined types.
> You could simply define that for built-in types :+: is exactly equivalent
to
> +    Or am I missing the point here?
> > Perhaps this could be in a future version of D, but let's defer that for now.
> ok.  It's nice to think that the language isn't static, and that we have
the
> time to slowly learn what the truly useful features are! :)

If there are too many features, we're back in the same boat as C++!



February 13, 2002
Walter wrote:

> I've been thinking a lot about operator overloading.
>
> 1) The idea of 'special' operators for overloading, like :+: being the overloadable version of +, is a good idea, but it fails when used with templates.
>
> 2) Overloaded operator functions should be inlineable, which lets out interfaces.
>
> 3) I just don't like the idea of operator functions having hidden arguments:
>
>     int operator+(int y);
>
> A binary operator function should, gosh darn it, have TWO operands:
>
>     static int operator+(Foo x, int y);

I prefer declaring a new or overloaded operator to EXACTLY resemble a function declaration.  Where, buy default, most functions are "prefix" (the function name comes first, followed by arguments), operators can be infix (function name between arguments, arguments limited to exactly two) or even postfix (function name follows all arguments).  Let's allow for the whole gamut!

M4 is smart enough to handle such notation, and I've used it with several languages where I was desperate to use non-prefix function call notations.

In the following, please excuse my use of caps and long names:  I do not advocate their use as-is, but I want to make it clear what I'm doing.

So, given the following:

   int foo( int, int) {...};
and
   int x = foo(1,2);

We could easily have:

   INFIX_OPERATOR int foo(IN int, IN int) {...};
and
   x = 1 foo 2;

Or even this:

  INFIX_OPERATOR myType +(IN myType, IN myType) {...};
and
  myType x, y, z;
  ...
  x = y + z;

IMO, the context makes the intent clear and easily parseable.

Now, let's talk about our favorite C feature, assignment operators.  Can we declare those as well?  Let's try:

   ASSIGNMENT_OPERATOR myType +=(IN OUT myType, IN myType) {...};

The ASSIGNMENT_OPERATOR is similar to INFIX_OPERATOR, except that the first parameter must be an IN OUT parameter.  This notation would also allow:

   myType a, b, c, d;

   d += a += c += b;

Yes, of course, assignments are valid on the right hand side.  To preclude this behavior, you'd need to define the function as returning void. Then the above statement would issue a type error for all assignments before the last one. (Strange, but true...)


I see no need for any explicit "overload" notation.  If someone decides to re-define integer addition, then the compiler should issue a warning ("Built-in operator being redefined."), but then let things proceed.  If turning off all implicit conversion is required when this feature is used, so be it: Caveat Emptor!

I, for one, would IMMEDIATELY use this feature to implement the "smart integer" features (similar to having NAN in D's floats) I was seeking in a long ago thread.

This notation should also be "template safe", for quite a large set of ways to define templates.  Should we discuss templates next?


> 4) I don't see a point to smart pointers and such in a garbage collected language. Overloadable operators should be restricted to arithmetic operators.

No, why not let it all hang out?  Let the compiler spew warning ad nauseum. But don't deny us the power to royally screw things up!


> 5) Operator overloading should only be used to provide arithmetic operations on user defined arithmetic types. None of that << and >> for iostreams. I know many people like that, but a shift is not a stream operation. It just isn't.

My prior comment applies!


> 6) I see no way to have the compiler enforce (5). Anyone caught violating
> (5) should be forced to carry the Stone of Shame.

No, they should be forced to endure "The Constant Stream Of Compiler Whining And Complaining".

Sort of like what "gcc -Wall" does to my code...  ;^)


> 7) Note (3) means no virtual operator functions. To do that, you'd need:
>     static int operator+(Foo x, int y)
>     {
>         return x.myadd(y);
>     }
> so no great loss.

I think my proposed


> 8) If there are to be conversion operators, they will not participate in implicit conversions, only explicit ones.

Agreed!  The price for such power should be to force the user to be extremely explicit about what they are doing.  Once you overload a predefined operator, the compiler should do no additional favors for you.  Other than complain, of course!


> None of this is implemented or specified yet, it's just some thoughts.

And very good ones.

I do NOT believe any such features of D need to be "efficient" or "optimizable".  If they are, that would be great.  All I ask is that they be "possible".


-BobC


February 13, 2002
Walter wrote:

> If there are too many features, we're back in the same boat as C++!

Umm, we could go straight for "D++", couldn't we?  (And no, I'm under no illusions of who "we" refers to.)


-BobC


February 13, 2002
"Pavel Minayev" <evilone@omen.ru> wrote in message news:a4bqaq$1buk$1@digitaldaemon.com...
> "Walter" <walter@digitalmars.com> wrote in message news:a4bm6j$1a5o$2@digitaldaemon.com...
>
> > If just a cmp() was provided, that can be used for all the comparisons.
>
>
> Hmmm... operator cmp?
>
>     enum Relation { Less, Equal, Greater }    // builtin
>
>     Relation operator cmp(vector a, vector b)
>     {
>         ...
>     }

No, it would return an int <0, 0, or >0. That makes it more efficiently implementable.


February 13, 2002
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3C6979F9.D014E2C8@deming-os.org...
> Walter wrote:
>
> > If just a cmp() was provided, that can be used for all the comparisons.
>
> True, but that is only for things that are reasonably ordered.  Some
things
> may have a property of equality/inequality but not ordering.  In that
case,
> you want to supply == and != but not < > <= >=
>
> Think (literally) apples and oranges :)

Object.cmp() exists already, and I figure just use that. And everyone knows that apples come before oranges <g>.


February 13, 2002
"Walter" <walter@digitalmars.com> wrote in message news:a4d8gg$1ult$3@digitaldaemon.com...

> No, it would return an int <0, 0, or >0. That makes it more efficiently implementable.

Either way, it'd make things simplier in many cases. Provide cmp, and other comparison ops are already there...


February 13, 2002
"Walter" <walter@digitalmars.com> wrote in message news:a4d8gh$1ult$4@digitaldaemon.com...

> Object.cmp() exists already, and I figure just use that. And everyone
knows
> that apples come before oranges <g>.

You mean that operators can only be overloaded for Objects? Not even structs?


February 13, 2002
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> ha scritto nel messaggio news:3C690E8D.37852B1@deming-os.org...
> Pavel Minayev wrote:
>
> > > 4) I don't see a point to smart pointers and such in a garbage
collected
> > > language. Overloadable operators should be restricted to arithmetic operators.
> >
> > I suppose you mean binary + - * / & | ^ ~ and unary ++ -- ~ ! and all the op= operators?
> >
> > The question is, should logical operators be overloaded?
>
> I would like to see the compiler provide the remaining logical operators
if only
> a few are defined.  That is, if you define
>
> operator==(Foo,int);
>     and
> operator<(Foo,int);
>
> (or any other combination of equality and inequality operators) the
compiler
> should be able to provide the rest.  Of course, it won't always be 100% optimized...but if it's not, you can provide the rest of the operators yourself.  I just always hated having to have 4 extra useless functions
just to
> define !=  <=  >= and > for every class.

In my classes I often use as example the operator <= (_the_ order operator
for mathematics): all other comparisons can be made with this (if the order
is total).

In C++:

bool operator <=(MyClass a, MyClass b)
{
   ...  implement this
}

// theese are "automatic"
inline bool operator == (MyClass a, MyClass b)
{
    return (a <= b) && (b <= a);
}
inline bool operator < (MyClass a, MyClass b)
{
    return (a <= b) && !(a == b);
}

// theese are simplicistic
inline bool operator != (MyClass a, MyClass b)
{
    return !(a == b);
}

inline bool operator > (MyClass a, MyClass b)
{
    return !(a <= b);
}

inline bool operator >= (MyClass a, MyClass b)
{
    return !(a < b);
}

OK, this work if the order is total, so (a<=b) && (b <= a) implies a == b .

Ciao