From slices to perfect imitators: opByValue

Timon Gehr via Digitalmars-d digitalmars-d at puremagic.com
Thu May 8 02:57:42 PDT 2014


On 05/08/2014 05:58 AM, Andrei Alexandrescu wrote:
> ...
> >
> import std.stdio;
>
> void fun(T)(T x)
> {
>     writeln(typeof(x).stringof);
> }
>
> void main()
> {
>     immutable(int[]) a = [ 1, 2 ];
>     writeln(typeof(a).stringof);
>     fun(a);
> }
>
> This program outputs:
>
> immutable(int[])
> immutable(int)[]
>
> which means that the type of that value has subtly and silently changed in the process of passing it to a function.
> ...

This way of stating it is imprecise: What happened is that during 
implicit function template instantiation, T was determined to be 
immutable(int)[] instead of immutable(int[]). Then 'a' was implicitly 
converted from immutable(int[]) to immutable(int)[] just as it would be 
done for any function call with those argument and parameter types.

> This change was introduced a while ago (by Kenji I recall) and it enabled a lot of code that was gratuitously rejected.
> This magic of T[] is something that custom ranges can't avail themselves
> of.  In order to bring about parity, we'd need to introduce opByValue
> which (if present) would be automatically called whenever the object is
> passed by value into a function.
> ...

There are two independent pieces of magic here, and this proposal 
removes none of them in a satisfactory way:

struct S(T){
     HeadUnqual!(typeof(this)) opByValue(){ ... }
     ...
}

void fun(in S!int a){}

void main(){
     const S!int s;
     fun(s); // error, cannot implicitly convert expression s.opByValue
             // of type S!(const(int)) to const(S!int).
}


A better ad-hoc way of resolving this is opImplicitCast and a special 
opIFTIdeduce member or something like that.

struct S(T){
     alias opIFTIdeduce = HeadUnqual!(typeof(this));
     S opImplicitCast(S)(typeof(this) arg){ ... }
     ...
}

But this just means that now every author of a datatype of suitable kind 
has to manually re-implement implicit conversion rules of T[].

A probably even better way is to just allow to specify by annotation 
that some templated datatype should mimic T[]'s implicit conversion 
rules (and without necessarily providing a direct and overpowered hook 
into the IFTI resolution process, though both could be done.)

> This change would allow library designers to provide good solutions to
> making immutable and const ranges work properly - the way T[] works.
> ...

Questionable.

const(T)[] b = ...;
const(T[]) a = b; // =)
Range!(const(T)) s = ...;
const(Range!T) r = s; // =(



More information about the Digitalmars-d mailing list