August 13, 2002
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.

August 13, 2002
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.

August 14, 2002
"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



August 14, 2002
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
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.
>


August 14, 2002
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. =)
August 14, 2002
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.
August 15, 2002
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>
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. =)


August 17, 2002
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

August 17, 2002
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.

August 17, 2002
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?