On Tue, Jun 11, 2013 at 11:08 PM, deadalnix <span dir="ltr"><<a href="mailto:deadalnix@gmail.com" target="_blank">deadalnix@gmail.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
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.<br>

<br>
struct Array(T) {<br>
    size_t length;<br>
    T* ptr;<br>
    // Methods<br>
}<br>
<br>
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.<br>

<br>
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.<br>
<br>
So I propose to introduce the inout template parameter type. We declare as follow :<br>
<br>
Array(inout T) {<br>
    size_t length;<br>
    T* ptr<br>
}<br>
<br>
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).<br>
<br>
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.<br>

<br>
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.<br>
<br>
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.<br>

<br>
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)));<br>

<br>
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.<br>

</blockquote></div><br><div><br></div><div>Why not use a castConstSafe function that'll transform A!T into A!(const T), generically:</div><div><br></div><div>auto ref castSafe(T,S)(auto ref S a){...} </div><div>S a; T b=castSafe!T(a); //same as T b=cast(T)(a) except that it only compiles if S=>T only involves nonconst=>const conversions (works recursively):</div>
<div>example: A!(double) => A!(const double) is allowed but not other direction.</div><div><div><br></div><div>More specifically:</div><div>auto ref castConstSafe(S)(auto ref S a){...} //transforms A!T into A!(const T), generically</div>
</div><div><br></div><div>then:</div><div>void foo(B a) if (is(ElementType!B == const)){...}</div><div><div>A!(const double) a1;</div><div>A!(double) a2;</div><div><div>foo(a1.castConstSafe); //works </div></div></div><div>
<div>foo(a2.castConstSafe); //works</div></div><div><br></div><div>All it requires is to pass a.castConstSafe instead of a.</div><div><br></div>