Function templates do implicit conversions for their arguments

TommiT tommitissari at hotmail.com
Thu Jul 4 13:11:55 PDT 2013


On Thursday, 4 July 2013 at 19:49:59 UTC, Maxim Fomin wrote:
> On Thursday, 4 July 2013 at 19:00:51 UTC, TommiT wrote:
>>> Note, that T is Toy, so there were no type conversion during 
>>> template instantiation. There was argument conversion after 
>>> instantiation, as it happens usually. Back to foo function 
>>> accepting slice - dmd does the same thing.
>>
>> DMD doesn't do the same thing for static arrays. Due to alias 
>> this, your Toy is a Wrap!Toy for all intents and purposes. 
>> There's no is-a relationship between a static array type and 
>> the dynamic array type which it implicitly converts to. What 
>> happens when static array implicitly converts to dynamic array 
>> is the same type of implicit conversion which happens when 
>> long converts to double. There's no is-a relationship between 
>> long and double.
>
> The idea that situation with alias this and arrays is 
> functionally different is simply defeacted by
>
> static assert (is(int[1] : int[]));
> static assert (is(Toy : Wrap!Toy));
> static assert (!is(int[1] == int[]));
> static assert (!is(Toy == Wrap!Toy));

Is-a relationship between types means this type of thing:

class Human { }

class Baby : Human { }

void main()
{
     static assert(!is(Baby == Human));
}

Baby is-a Human, but the type Baby is not same as Human.

If static arrays used an alias this to convert to a dynamic 
array, then you'd able to append to a static array:

struct DynamicArray(T)
{
     void opOpAssign(string op : "+")(int n) { }
}

struct StaticArray(T, int size)
{
     alias get this;

     DynamicArray!T get() @property
     {
         return DynamicArray!T.init;
     }
}

void main()
{
     StaticArray!(int, 4) sa;
     sa += 42; // Can't do this with static arrays
}


On Thursday, 4 July 2013 at 19:49:59 UTC, Maxim Fomin wrote:
> On Thursday, 4 July 2013 at 19:00:51 UTC, TommiT wrote:
>>> See above. What type implicit converision did dmd in case of 
>>> int[10] and int[]. Conversion from int to int?
>>
>> Here's what the compiler does during type deduction when it 
>> sees the following function template and its instantiation:
>>
>> void foo(T)(T[] da) { }
>>
>> int[10] sa;
>> foo(sa);
>>
>> <steps follow ...>
>
> This is nice and interesting to read. Please provide references 
> to dmd code which support the description of dmd compiling 
> process you provided (judging by how confident in this topic 
> you are, you might have studied cast.c, expression.c and 
> template.c wery well). Without such references any text 
> pretending to tell something about what compiler does is cheap.

I have never seen any DMD code. My deduction of how DMD _must_ 
work is based on:
1) my understanding of how template instantiation works in C++
2) the fact that the call to foo(sa) does compile

The compiler simply must know about implicit conversion of static 
to dynamic arrays during template instantiation, or otherwise it 
wouldn't be able to do the instantiation of foo for the call to 
foo(sa). And not only that, the compiler must accept a non-exact 
match between parameter and argument types. C++ never accepts 
anything but an exact match between the parameter types of the 
instantiated template function and the types of the arguments 
passed in to the function at the call site which caused the 
instantiation. That's pretty simple logic, which is why I'm 
confident that I'm right even though, like I said, I don't know 
anything about how DMD is written.


More information about the Digitalmars-d mailing list