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