inout template parameter, or a solution to the templated container issue

Jason House jason.james.house at gmail.com
Wed Jun 12 06:31:17 PDT 2013


On Wednesday, 12 June 2013 at 06:08:58 UTC, deadalnix wrote:
> We currently have a problem with containers : it is very 
> difficult to implement them in a way that is compliant type 
> qualifiers. To restate the problem shortly, let's imagine we 
> want to implement array's as a library type.
>
> struct Array(T) {
>     size_t length;
>     T* ptr;
>     // Methods
> }
>
> Now we have several problems with type qualifiers. For 
> instance, Array!T won't implicitly cast to Array!const(T), and 
> const(Array!T) now become a completely useless type, as ptr 
> will become const by transitivity which will create internal 
> inconsistencies.
>
> This problem is known and makes it hard to provide a nice 
> container library for D. This also imply a lot of circuitry in 
> the compiler that can (and should) be provided as library.
>
> So I propose to introduce the inout template parameter type. We 
> declare as follow :
>
> Array(inout T) {
>     size_t length;
>     T* ptr
> }
>
> The inout template parameter is a type parameter, and so don't 
> overload on them (if both Array(T) and Array(inout T) the 
> instantiation is ambiguous).
>
> Within the template, T is always seen as inout, and only one 
> instantiation occur for all top type qualifiers. Array!T and 
> Array!const(T) refers to the same instance of Array. As a 
> result, this makes it impossible to specialize Array on T's 
> type qualifier.
>
> The real type qualifier is determined from the outside. A user 
> of Array!T consider inout as meaning mutable, when a user of 
> Array!const(T) consider it as meaning const, for anything 
> related to Array.
>
> Implicit cast is allowed for instances of Array with different 
> inout parameter's type qualifier, as long as implicit 
> conversion between such qualifier is allowed. Array!T 
> implicitly convert to Array!const(T) but not the other way 
> around.
>
> Finally, Array's type qualifier turtle down to inout 
> parameters's type qualifier. alias A = Array!T; static 
> assert(is(const(A)) == const(Array!const(T))); alias B = 
> Array!immutable(T); static assert(is(const(A)) == 
> const(Array!immutable(T)));
>
> The idea popped in my mind yesterday, so it is not really super 
> fleshed out, and I'm not sure if some horrible dark corner case 
> makes it completely worthless. But it seems super promising to 
> me, so I want to share. The current situation isn't satisfying 
> and we desperately need a solution.

I think it needs to be fleshed out better...  Try to add the 
methods to your array class and think through the required 
validation. For example, an insert of const(T) would only work if 
implemented as a copy on write. It would also be good to think 
through how to handle class hierarchies.

I believe the correct handling requires awareness of covariant 
and contravariant types. I first heard about them in scala, but I 
think C# generics use a better syntax. If I remember correctly, 
you'll need two type arguments: array(in I, out O), where I is 
implicitly castable to O. If C derives from B which derives from 
A, then array!(B,B) is implicitly castable to array!(C,B), 
array!(B,A), and array!(C,A)



More information about the Digitalmars-d mailing list