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

Timothee Cour thelastmammoth at gmail.com
Wed Jun 12 02:16:09 PDT 2013


On Tue, Jun 11, 2013 at 11:08 PM, deadalnix <deadalnix at gmail.com> 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.
>


Why not use a castConstSafe function that'll transform A!T into A!(const
T), generically:

auto ref castSafe(T,S)(auto ref S a){...}
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):
example: A!(double) => A!(const double) is allowed but not other direction.

More specifically:
auto ref castConstSafe(S)(auto ref S a){...} //transforms A!T into A!(const
T), generically

then:
void foo(B a) if (is(ElementType!B == const)){...}
A!(const double) a1;
A!(double) a2;
foo(a1.castConstSafe); //works
foo(a2.castConstSafe); //works

All it requires is to pass a.castConstSafe instead of a.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20130612/fd54f735/attachment.html>


More information about the Digitalmars-d mailing list