On Tue, 15 Dec 2009 23:43:58 -0500, Walter Bright <newshou...@digitalmars.com> wrote:

Andrei Alexandrescu wrote:
Time has come to make a decision on implementing Steven Schveighoffer's proposal:

Unmentioned in the proposal is is inout a type constructor or a storage class? For example,

     U[inout(T)]* foo(inout(X)*** p) { ... }

type constructor. it has no meaning as a storage class since it's entirely transient (it only has any meaning inside functions). You should never be able to declare any part of a global or member variable as inout, because its meaning can change once a function exits. It's almost a beast of it's own, it's mostly like const, but has some quirky extra rules.

BTW, I'm unsure if U[inout(T)] should work. Can one implicitly cast U[T] to U[const(T)] ? If not, then it doesn't make sense that U[inout(T)] should even compile. I guess the rule should be if you have a type that contains an inout notation, the complier should verify that if you define 2 types, one that removes all inout decorations, called M, and one that replaces all inout decorations with const, called N, you should be able to cast from M to N implicitly. If not, then the inout type is invalid.

For example:

int[inout(char)[]]:

int[char[]] => M
int[const(char)[]] => N


This is much more complex to implement than only allowing inout at the top level, i.e. as a storage class.

A storage class does not give you the transitivity that you need to enforce const rules. The inout tag must be carried forth to aliases of the same data.


I also prefer the idea of inout on the return type being assumed, rather than explicit:

     T foo(inout U p) { ... }

What about this?

T[] foo(inout(U)[] p) {...}

Should the return type implicitly be inout(T)[] or inout T[] ?

-Steve

Reply via email to