transporting qualifier from parameter to the return value

Steven Schveighoffer schveiguy at yahoo.com
Tue Dec 15 21:09:32 PST 2009


On Tue, 15 Dec 2009 23:43:58 -0500, Walter Bright  
<newshound1 at 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



More information about the Digitalmars-d mailing list