DMD 0.177 release

Kevin Bealer kevinbealer at gmail.com
Thu Dec 14 21:00:05 PST 2006


== Quote from Andrei Alexandrescu (See Website for Email) > Now consider:
> struct S {
>    int a;
>    S opAssign(int x) {
>      a = x;
>      return this;
>    }
> }
> void Increment(inout S x) {
>    ++x.a;
> }
> S a;
> Increment(a = 5);
> This is going to have very different (and useless and unwanted) semantics.
> Again, the right thing to do: give the Caesar what belongs to the
> Caesar. Have the user do the assignment (and return void), and have the
> compiler pass the lhs lvalue around, when needed.
> Andrei

This reminds me of the "opIndex" discussion we had here quite a while ago.  The
problem was that for user defined containers, you can't simulate X[i] if the
contained type is something like a struct.

class C {
   S s1;

   S opIndex(int i)
   {
      return s1;
   }
}

There is an opIndexAssign(), but it has the same problem when applied to the inout
parameter.

>From the discussion at the time (Ben Hinkle might remember) I recall two
possibilities that seemed to make sense to me.

1. Add a return type qualifier with "inout" semantics, like a C++ "&" type.

    Something like one of these, inout of course looks a bit funny:

    ref S opIndexRef(int i);
    inout S opIndexRef(int i);

2. Return S* and let the compiler apply the "*".

    S* opIndex(int i);
    Compiler silently transforms foo(x[i]) into foo(*x[i])

I think #2 is a lot like what has been suggested for opAssign():

A* A::opAssign(inout A b);
S* A::opIndexAssign(int i);

assign1: a.opAssign(b)      -> (a.opAssign(b), a)
assign2: a.opAssign(b)      -> *(a.opAssign(b))
index1:  a.opIndexAssign(i) -> *opIndexAssign(i)

Where index1 is my opIndex suggestion (from way back) and assign1 and assign2 are
Walter and Andrei's possible syntaxes for opAssign() respectively.

Conceptually, the problem looks similar to me: how to "tunnel" an assignable type
through a return value of a method, like the C++ "&" types do.  The opIndex
version needs to tunnel up through more layers than opAssign() does since it's not
the A type, so the (a.opIndex(b), a) can't work there of course.

I would vote for "S*" being the conceptual return type in both cases for
opAssign() and opIndex(), although in the case of opAssign() it wouldn't bother me
if the user visible signature was "void opAssign(...)" and the compiler handles
the pointer as it does with this().

Kevin



More information about the Digitalmars-d-announce mailing list