Jump to page: 1 210  
Page
Thread overview
Operator overloading: A way to make everybody happy?
Jan 22, 2002
OddesE
Jan 22, 2002
Sean L. Palmer
Jan 22, 2002
Walter
Jan 23, 2002
Roberto Mariottini
Jan 24, 2002
Walter
Jan 24, 2002
Roberto Mariottini
Jan 25, 2002
Walter
Jan 24, 2002
OddesE
Re: Operator overloading: A way to make somebody happy?
Jan 25, 2002
Juarez Rudsatz
Jan 25, 2002
Russ Lewis
Jan 25, 2002
OddesE
Jan 26, 2002
Sean L. Palmer
Jan 26, 2002
Russell Borogove
Feb 12, 2002
Walter
Feb 12, 2002
D
Feb 12, 2002
Pavel Minayev
Feb 12, 2002
Russ Lewis
Feb 12, 2002
Pavel Minayev
Feb 12, 2002
Russ Lewis
Feb 12, 2002
Pavel Minayev
Feb 12, 2002
Walter
Feb 12, 2002
Pavel Minayev
Feb 13, 2002
Walter
Feb 13, 2002
Pavel Minayev
Feb 12, 2002
Russ Lewis
Feb 12, 2002
Pavel Minayev
Feb 13, 2002
Walter
Feb 13, 2002
Pavel Minayev
Feb 12, 2002
Sean L. Palmer
Feb 13, 2002
Roberto Mariottini
Feb 12, 2002
Russ Lewis
Feb 12, 2002
Walter
Feb 12, 2002
Russ Lewis
Feb 12, 2002
Pavel Minayev
Feb 13, 2002
Roberto Mariottini
Feb 13, 2002
Pavel Minayev
Feb 16, 2002
OddesE
Feb 12, 2002
Walter
Feb 12, 2002
Sean L. Palmer
Feb 12, 2002
Pavel Minayev
Feb 04, 2002
D
Feb 04, 2002
Sean L. Palmer
Feb 05, 2002
D
Feb 05, 2002
OddesE
Feb 06, 2002
D
Feb 06, 2002
Pavel Minayev
Feb 07, 2002
D
Feb 04, 2002
Russ Lewis
Feb 05, 2002
D
Feb 06, 2002
Serge K
Feb 06, 2002
Russell Borogove
Feb 06, 2002
Roberto Mariottini
Feb 07, 2002
D
Feb 08, 2002
Roberto Mariottini
Feb 09, 2002
D
Feb 09, 2002
D
Feb 06, 2002
D
Feb 06, 2002
Pavel Minayev
Feb 07, 2002
D
Feb 04, 2002
OddesE
Feb 05, 2002
D
Feb 05, 2002
Pavel Minayev
Feb 05, 2002
D
Feb 05, 2002
Roberto Mariottini
Feb 05, 2002
D
Feb 05, 2002
OddesE
Feb 06, 2002
D
Feb 07, 2002
OddesE
Mar 07, 2002
Immanuel Scholz
Mar 07, 2002
Pavel Minayev
Mar 07, 2002
OddesE
Mar 08, 2002
Pavel Minayev
Mar 08, 2002
Russ Lewis
Mar 08, 2002
Russ Lewis
Mar 08, 2002
Pavel Minayev
Mar 08, 2002
Russ Lewis
Mar 08, 2002
Pavel Minayev
Mar 08, 2002
Russ Lewis
Mar 08, 2002
Immanuel Scholz
Mar 08, 2002
Pavel Minayev
Mar 08, 2002
Immanuel Scholz
Mar 08, 2002
Pavel Minayev
Mar 08, 2002
Immanuel Scholz
Mar 08, 2002
Pavel Minayev
Mar 08, 2002
Roland
Mar 08, 2002
Russell Borogove
Mar 10, 2002
Walter
January 22, 2002
Ok, so one more time about operator overloading...  :)

I read all the posts about operator overloading but I'm still a bit unsure about it...Do I want it, or don't I...

I like about operator overloading the fact that you
can add, subtract, compare or assign objects to
one another much the same way as you can with
normal primitive types.

I hate some uses of operator overloading which
seem really confusing to me. I always disliked
the way cout and cin work.

But maybe there is some middle ground?
A compromise that could make everybody happy?

Here is my idea:

Think of Java, if you know it. It contains interfaces
just like D. One of these interfaces is called Clonable.
If you want your object to be copied to another,
you implement Clonable. Now what if we could
combine these kinds of interfaces with a form of
predefined operator overloading. You would have
a few predefined interfaces:

IComparable, IAssignable, ISortable, IAddable,
ISubtractable, IMultiplyable, IDividable...you get
the idea.

D would be able to check if an object implemented
any of these interfaces and would automagically
provide the suitable operators.

I have already tried to implement something like
this in C++ and I actually got IAssignable and
IComparable to work, but when I tried to add
more I got into trouble with multiple inheritance.

Just a thought, but I think this might be a solution
that would make everybody happy!


P.S: There is another thread about templates which
contains some sort of a variation on this:
Constrained Genericity (template suggestion)

--
Stijn
OddesE_XYZ@hotmail.com
http://OddesE.cjb.net
__________________________________________
Remove _XYZ from my address when replying by mail




January 22, 2002
That could be an easy way to deal with the syntax part of it.  Sounds promising.  I assume the operator would just map to a "normal" looking pure virtual function, such as Addable Add(Addable other), which could then be overridden.

Unfortunately in D all functions are virtual, so the calling overhead will be large, but at least it would be possible to accomplish the goal of making a class work like a built-in type.

Sean

"OddesE" <OddesE_XYZ@hotmail.com> wrote in message news:a2k8u8$fao$1@digitaldaemon.com...
> Ok, so one more time about operator overloading...  :)
>
> I read all the posts about operator overloading but I'm still a bit unsure about it...Do I want it, or don't I...
>
> I like about operator overloading the fact that you
> can add, subtract, compare or assign objects to
> one another much the same way as you can with
> normal primitive types.
>
> I hate some uses of operator overloading which
> seem really confusing to me. I always disliked
> the way cout and cin work.
>
> But maybe there is some middle ground?
> A compromise that could make everybody happy?
>
> Here is my idea:
>
> Think of Java, if you know it. It contains interfaces
> just like D. One of these interfaces is called Clonable.
> If you want your object to be copied to another,
> you implement Clonable. Now what if we could
> combine these kinds of interfaces with a form of
> predefined operator overloading. You would have
> a few predefined interfaces:
>
> IComparable, IAssignable, ISortable, IAddable,
> ISubtractable, IMultiplyable, IDividable...you get
> the idea.
>
> D would be able to check if an object implemented
> any of these interfaces and would automagically
> provide the suitable operators.
>
> I have already tried to implement something like
> this in C++ and I actually got IAssignable and
> IComparable to work, but when I tried to add
> more I got into trouble with multiple inheritance.
>
> Just a thought, but I think this might be a solution
> that would make everybody happy!
>
>
> P.S: There is another thread about templates which
> contains some sort of a variation on this:
> Constrained Genericity (template suggestion)
>
> --
> Stijn
> OddesE_XYZ@hotmail.com
> http://OddesE.cjb.net
> __________________________________________
> Remove _XYZ from my address when replying by mail
>
>
>
>


January 22, 2002
"OddesE" <OddesE_XYZ@hotmail.com> wrote in message news:a2k8u8$fao$1@digitaldaemon.com...

> But maybe there is some middle ground?
> A compromise that could make everybody happy?

   Actually, there might be.

> Think of Java, if you know it. It contains interfaces
> just like D. One of these interfaces is called Clonable.
> If you want your object to be copied to another,
> you implement Clonable. Now what if we could
> combine these kinds of interfaces with a form of
> predefined operator overloading. You would have
> a few predefined interfaces:
>
> IComparable, IAssignable, ISortable, IAddable,
> ISubtractable, IMultiplyable, IDividable...you get
> the idea.
>
> D would be able to check if an object implemented
> any of these interfaces and would automagically
> provide the suitable operators.

   This is actually close to the concept of a "class" in Haskell. Haskell is
a very interesting language for anyone who's into programming languages.
It's designed from the ground up to be a pure functional language, which
usually makes the imperative programmer queasy, but it's actually a very
usable and mature language at this point.

   So, let me show a bit what Haskell calls classes. I'll change the syntax
so as to make it more D-like or C++-like:

---
typeclass Eq(a) {
  bool operator ==(a, a);
  bool operator !=(a, a);

  // Minimal complete defintion:
  //      (==) or (!=)
  // [JCAB] These are default definitions...

  bool operator ==(a x, a y) {
    return not(x != y);
  }
  bool operator !=(a x, a y) {
    return not(x == y);
  }
}
---

   This defines the class of all types (a is a type parameter) that have
equality comparison in them. Then, you can define your own types, like a 3D
vector:

---
class Vector3D {
  float x, y, z;
}
---

   And then (separately) give the vector the equality class:

---
typeclassinstance Eq(Vector3D) {
  bool operator ==(Vector3D v0, Vector3D v1) {
    return v0.x == v1.x && v0.y == v1.y && v0.z == v1.z;
  }
  // operator != gets implemented from the default.
}
---

   Of course, the implementation of something like this in D would follow
more what Stijn was saying. In Haskell, it is assumed that polymorphic
functions (and operators) like those defined in a type class like that can
have an extra "hidden" parameter called the dictionary (you can assume it's
like an extra virtual function table pointer) for each type class used in
the implementation of the function. Type classes in Haskell can require that
the type reference also implement other type classes (they call it
inheritance, which it is after a fashion). The standard set of Haskell
classes is:

class                             Bounded a
class                             Enum a
class                             Eq a
class           (Fractional a) => Floating a
class                  (Num a) => Fractional a
class                             Functor f
class         (Real a, Enum a) => Integral a
class                             Monad m
class   (Eq a, Show a, Eval a) => Num a
class                   (Eq a) => Ord a
class                             Read a
class           (Num a, Ord a) => Real a
class (RealFrac a, Floating a) => RealFloat a
class   (Real a, Fractional a) => RealFrac a
class                             Show a

   where => means "is required for".

   BTW, Haskell allows the programmer to use any sequence of symbol
characters as operators, like +++ or <=|=>. And define their precedence and
associativity.

Salutaciones,
                         JCAB



January 22, 2002
"Sean L. Palmer" <spalmer@iname.com> wrote in message news:a2kevr$j2g$1@digitaldaemon.com...
> That could be an easy way to deal with the syntax part of it.  Sounds promising.  I assume the operator would just map to a "normal" looking
pure
> virtual function, such as Addable Add(Addable other), which could then be
> overridden.
>
> Unfortunately in D all functions are virtual, so the calling overhead will be large, but at least it would be possible to accomplish the goal of
making
> a class work like a built-in type.
>
> Sean

It is an interesting idea.

While D defines all functions to be virtual, a good optimizing compiler can de-virtualize (!) any functions which are not overridden by a derived class. This is one example where D simplifies programming and reduces errors. In my C++ work, I do this manually (then I add a derived class, forget to add "virtual", and have a subtle bug. Argh!). Since an optimizing D compiler will de-virtualize all calls it can, it can potentially have many *fewer* virtual calls than the equivalent C++ program.


January 23, 2002
"Walter" <walter@digitalmars.com> ha scritto nel messaggio news:a2km7g$o9f$1@digitaldaemon.com...
>
[...]
> While D defines all functions to be virtual, a good optimizing compiler
can
> de-virtualize (!) any functions which are not overridden by a derived
class.
> This is one example where D simplifies programming and reduces errors. In
my
> C++ work, I do this manually (then I add a derived class, forget to add "virtual", and have a subtle bug. Argh!). Since an optimizing D compiler will de-virtualize all calls it can, it can potentially have many *fewer* virtual calls than the equivalent C++ program.

Here Java has a point: a 'final' class cannot be derived, so the optimizing
compiler can
de-virtualize all functions it can.
When you try to derive from this class the compiler signal an error, so you
can remove
the little 'final' word and recompile safely.

Ciao


January 24, 2002
"Roberto Mariottini" <rmariottini@lycosmail.com> wrote in message news:a2ls2g$1hvv$1@digitaldaemon.com...
> Here Java has a point: a 'final' class cannot be derived, so the
optimizing
> compiler can
> de-virtualize all functions it can.
> When you try to derive from this class the compiler signal an error, so
you
> can remove
> the little 'final' word and recompile safely.

True, but to me that 'final' keyword is there to compensate for a weakness in the optimizer. It's unnecessary.


January 24, 2002
"Walter" <walter@digitalmars.com> ha scritto nel messaggio news:a2nt3r$2v4f$3@digitaldaemon.com...
>
> "Roberto Mariottini" <rmariottini@lycosmail.com> wrote in message news:a2ls2g$1hvv$1@digitaldaemon.com...
> > Here Java has a point: a 'final' class cannot be derived, so the
> optimizing
> > compiler can
> > de-virtualize all functions it can.
> > When you try to derive from this class the compiler signal an error, so
> you
> > can remove
> > the little 'final' word and recompile safely.
>
> True, but to me that 'final' keyword is there to compensate for a weakness in the optimizer. It's unnecessary.

Ok, but this little word can work like C "register" one:
 - You don't need an optimizer to do easy optimization. Consider that not
every compiler
    has a (good) optimizer, especially alpha or beta compilers ;-)
 - A final class can be safely optimized even in debug releases, this will
ease debugging.
 - The average optimizer is simpler to write.
 - A good optimizer can optimize even non-final classes (and even ignore
final ones), as you stated,
   and as the 'register' keyword works in C.

PS: I suppose there is no 'register' keyword in D, right?

Ciao


January 24, 2002
"Sean L. Palmer" <spalmer@iname.com> wrote in message news:a2kevr$j2g$1@digitaldaemon.com...
> That could be an easy way to deal with the syntax part of it.  Sounds promising.  I assume the operator would just map to a "normal" looking
pure
> virtual function, such as Addable Add(Addable other), which could then be
> overridden.
>
> Unfortunately in D all functions are virtual, so the calling overhead will be large, but at least it would be possible to accomplish the goal of
making
> a class work like a built-in type.
>
> Sean


That is indeed exactly what I was thinking of.
In my opinions there are at least three benefits to using such an
approach:

1.  You have a standardized way of creating "operators". If you
     would implement IAssignable, the operator = would work for
     your class. If you implement IAddable, then operator + would
     also work. Combining the two would automatically give you
     operator += as well. Because the routines are standardized,
     and because D would make smart combinations of routines to
     give you combined operators such as +=, you would have to
     implement less functions to support more operators and errors
     would be made less frequently.

2.  Everyone can choose. If the interface IAddable would contain
     a pure virtual method Add(), this would be standard. So people
     can choose wheter to use Add() or +, knowing they will always
     be both fully supported and work exactly the same, or both of
     them won't be supported at all. Hell, using DML you could
     even allow both forms to be exchanged into one another
     depending on a preferences setting.

3.  You can detect wheter a class supports a certain type of
     operator. Using RTTI you can determine if a class IS A
     IAddable or not. This might be *very* valuable. This could
     also be used to force a class to support an operator. How
     about:  COrderedList.Insert (ISortable element)  ?


I also see some problems for this approach though:

1.  Speed. It might be too slow to implement operator overloading
     this way. But I really don't know how good or bad a compiler
     might optimise this. I imagine it would be possible for the compiler
     to change obj + obj to obj.Add (obj) at compile time, but I don't
     know if this is in fact possible.

2.  Operator 'dependencies'... Think of ISortable, it would probably
     have a method IsLess () or something, but it doesn't really make
     sense to implement that without implementing IComparable's
     IsEqual(). Now this problem isn't new, it is just an old problem
     that isn't solved. In C++ it is also possible to overload < but not
     ==. You could try to make ISortable inherit from IComparable,
     so implementing IsLess forces you to implement IsEqual too.
     I tried this in my C++ experiment but ran into trouble with
     virtual inheritance. I think that it should be possible using
     interfaces though...


To give you more of a feeling of how it would work, I'll post some sample code. I'm typing this in my newsreader, so please forgive me my 'spelling'.  :)


interface IAssignable
{
     void Assign (Object obj);
     void Assign (int i);
     void Assign (bool b);
     void Assign (double d);
     void Assign (char c);
     // ... It gets dull, but you get the idea
     // One Assign for Object's and one for
     // each standard type.
}

interface IAddable
{
     void Add (Object obj);
     // ...
}

interface ISubtractable
{
     void Subtract (Object obj);
     // ...
}

interface IDividable
{
     void Divide (Object obj);
     // ...
}

interface IMutiplyable
{
     void Multiply (Object obj);
     // ...
}

interface IComparable
{
     bool IsEqual (Object obj);
     // ...
}

interface ISortable: IComparable
{
     bool IsLess (Object obj);
     // ...
}

class CMyObject: IComparable
{
     public int m_i;

     this (int i) {m_i = i};

     bool IsEqual (Object obj)
     {
          CMyObject myObj = cast (CMyObject) obj;
          if (myObj == null)
               return false;
          return (this.m_i == myObj.m_i);
     }

     bool IsLess (Object obj)
     {
          CMyObject myObj = cast (CMyObject) obj;
          if (myObj == null)
               return false;
          return (this.m_i < myObj.m_i);
     }
}

// And how you would use it:

CMyObject obj1 = new CMyObject (10);
CMyObject obj2 = new CMyObject (13);

if (obj1 < obj2)
// Would call:
// if (obj1.Less (obj2))

if (obj1 <= obj2)
// Would call:
// if ((obj1.Less (obj2)) || (obj1.IsEqual (obj2)))

if (obj1 > obj2)
// Would call:
// if ((! obj1.Less (obj2)) && (! obj1.IsEqual (obj2)))

if (obj1 >= obj2)
// Would call:
// if ((! obj1.Less (obj2)))

Well that's about it.


Greets!

--
Stijn
OddesE_XYZ@hotmail.com
http://OddesE.cjb.net
__________________________________________
Remove _XYZ from my address when replying by mail



January 25, 2002
"Roberto Mariottini" <rmariottini@lycosmail.com> wrote in message news:a2p5j5$qlp$1@digitaldaemon.com...
> Ok, but this little word can work like C "register" one:
>  - You don't need an optimizer to do easy optimization. Consider that not
> every compiler
>     has a (good) optimizer, especially alpha or beta compilers ;-)

It isn't that hard to do the final optimization. You just look to see if there are any derived classes, and if any of those derived classes override it.

>  - A final class can be safely optimized even in debug releases, this will
> ease debugging.
>  - The average optimizer is simpler to write.

True, but I propose to simplify the language, and am willing to put a little more burden on the compiler to get that. You can remind me that I propose that D be easy to write a compiler for, and I respond that it isn't necessary for a compiler to implement this optimization!

>  - A good optimizer can optimize even non-final classes (and even ignore
> final ones), as you stated,
>    and as the 'register' keyword works in C.
>
> PS: I suppose there is no 'register' keyword in D, right?

Correct. C compilers haven't been dependent on it for over a decade.



January 25, 2002
This form could be a very good way of solving the problem for classes. But what the main purpose of operator overloading ?

For me is defining new operations over simple types. The are not strong meaning doing :

computer a, b, c;
a = new computer(1,2);
a = new computer(1,7);
c = a + b;

For example candidates could be
Date and Time,
Grades , Minutes, Seconds
Celsius <-> Fahrenheit
Meters <-> Foots
Kilo, Pounds, etc...
Matematic types like complex ( already added ) and so on
Geometric types
Matrix types
, and etc

How could this be done with interfaces.

"OddesE" <OddesE_XYZ@hotmail.com> wrote in message
news:a2k8u8$fao$1@digitaldaemon.com...
Ok, so one more time about operator overloading...  :)

I read all the posts about operator overloading but I'm still a bit unsure about it...Do I want it, or don't I...

I like about operator overloading the fact that you
can add, subtract, compare or assign objects to
one another much the same way as you can with
normal primitive types.

I hate some uses of operator overloading which
seem really confusing to me. I always disliked
the way cout and cin work.

But maybe there is some middle ground?
A compromise that could make everybody happy?

Here is my idea:

Think of Java, if you know it. It contains interfaces
just like D. One of these interfaces is called Clonable.
If you want your object to be copied to another,
you implement Clonable. Now what if we could
combine these kinds of interfaces with a form of
predefined operator overloading. You would have
a few predefined interfaces:

IComparable, IAssignable, ISortable, IAddable,
ISubtractable, IMultiplyable, IDividable...you get
the idea.

D would be able to check if an object implemented
any of these interfaces and would automagically
provide the suitable operators.

I have already tried to implement something like
this in C++ and I actually got IAssignable and
IComparable to work, but when I tried to add
more I got into trouble with multiple inheritance.

Just a thought, but I think this might be a solution
that would make everybody happy!


P.S: There is another thread about templates which
contains some sort of a variation on this:
Constrained Genericity (template suggestion)

--
Stijn
OddesE_XYZ@hotmail.com
http://OddesE.cjb.net
__________________________________________
Remove _XYZ from my address when replying by mail






« First   ‹ Prev
1 2 3 4 5 6 7 8 9 10