August 15, 2013
On Thursday, 15 August 2013 at 12:44:09 UTC, Tommi wrote:
>
> I don't expect int[3] to implicitly convert to int[] during type deduction for the same reason that I don't expect int to implicitly convert to long during type deduction (even though I know that int implicitly converts to long in all kinds of other contexts):
>
> void getLong(T)(T arg)
> if (is(T == long))
> {
> }
>
> void main()
> {
>     int n;
>     getLong(n); // int doesn't implicitly convert to long
> }
>

OK,

void getLong(T)(T arg)
if (is(T : long))
{
	
}

void main()
{
    int n;
    getLong(n); // int is implicitly convertible to long
}

now you have "implicit conversion from int to long during type deduction".

>> Also actual conversion happens later in some completely unrelated to type deduction compiler part.
>
> I know implicit conversion happens at a later stage (not during type deduction). But I don't have any other words to describe it other than saying "implicit conversion during type deduction". If you can provide me some more exact language, please do.

There is a test whether base types are equal (which happens in many stages, including type deduction) and conversion which happens in later stage.

>> Compiler "doesn't give the benefit to doubt" as there are no hints here about dynamic array.
>
> Why would the compiler need a hint? The compiler knows that the static array can implicitly convert to dynamic array, so it should be able to check if the function could be called with the argument first implicitly converted to a dynamic array.
>

Because I was speaking about general case. In this case yes, dmd can know beforehand that T[N] can be converted to T[]. In general case which can involve alias this (including multiple alias this) the problem can be more complex.
August 15, 2013
On 08/15/13 14:44, Tommi wrote:
[...]
> No, I'm not asking A -> C, I'm just asking that int[3] convert to int[].

>From you earlier post:

  Ret bar(R)(R r) // [6]
  if (std.range.isInputRange!R)
  {
      return Ret.input_range;
  }

You'd like to be able to call 'bar' with a static array. Currently
you can't, because 'R' becomes a /static array/, hence not a input range.

Note that

  Ret baz(R)(R[] r) // [6]
  if (std.range.isInputRange!(R[]))
  {
      return Ret.input_range;
  }

/would/ work. This case works, because 'baz' expects a dynamic array and static arrays implicitly convert to dynamic ones - so if there is no better fitting overload then the static->dynamic conversion will be done.

To make your case work, it would be necessary to first deduce R==int[3],
then try instantiating the template, and if this fails retry with whatever
int[3] implicitly converts to (int[] in this case).
The only alternative is making the static->dynamic array conversion
/mandatory/ when deducing types - which is not a good idea either.

The implicit int[3] -> int[] conversion should not exist.

artur
August 15, 2013
On Thursday, 15 August 2013 at 13:25:58 UTC, Maxim Fomin wrote:
> On Thursday, 15 August 2013 at 12:12:59 UTC, Tommi wrote:
>>
>> Implicit conversion VS Implicit conversion during type deduction
>> ----------------------------------------------------------------
>> I don't think that you failed to see the distinction between these two things, but because someone might, I'll talk about this a bit more.
>>
>> This is regular implicit conversion (nothing weird or magical about it):
>>
>> void foo(int[] da) { }
>> int[3] sa;
>> foo(sa); // implicit conversion
>>
>> This is implicit conversion during type deduction (totally weird and magical):
>>
>> void foo(T)(T[] da) { }
>> int[3] sa;
>> foo(sa); // implicit conversion during type deduction
>>
>
> Please stop spreading this misconveption. There is *no*
> conversion during type deduction. There is *a check* whether base
> type of static array is same as base type of dynamic array which
> happens to be true in this case. *Conversion* happens in
> completely related compiler part.

I've been saying "implicit conversion during type deduction", but I seriously doubt that anyone who knows what type deduction is, would think that actual implicit conversion somehow happens during that.

(Type deduction is simply figuring out what the actual type of a templated type is given a certain context).

But, from now on, I'll use the phrase "checking for implicit conversions during type deduction" instead of "implicit conversion during type deduction".

On Thursday, 15 August 2013 at 13:25:58 UTC, Maxim Fomin wrote:
> And there is no special about it during template type deduction.
> This (meaning that base type of int[N] array is same as base type
> of int[] array) happens or could happen in any stage of compiling
> proccess. How C++ does it is irrelevant to what D does.

I agree that what C++ does is irrelevant to what D does (I never said it was). I used an example of C++ code to make a point which _is_ relevant to D. Since you seemed to miss the point, I'm going to translate that previous C++ example code D code now to get my point across:

struct DynamicArray(T) { }

struct StaticArray(T, size_t n)
{
    DynamicArray!T opImplicitCast() const
    {
        return DynamicArray!T();
    }
}

void foo(T)(DynamicArray!T da) { }

void bar(DynamicArray!int da) { }

void main()
{
    StaticArray!(int, 5) sa;
    bar(sa); // OK: implicit conversion
    foo(cast(DynamicArray!int) sa); // OK: explicit conversion
    foo(sa); // Error: No matching function call to 'foo'
}

Don't try to compile that, it won't work because I used the opImplicitCast operator which is a future feature of D (it provides an implicit conversion for used defined types). How do I know it's a future feature of D? Don't ask... okay, you got me... I'm a time traveller.

Now, to fulfill my promise of being excruciatingly explicit: What said before about being a time traveller, it was a joke. My point is that D could have an implicit cast operator in the future. And if it did have it, then it would become obvious to everybody why it is that a static array, such as:

int[5]

...is magical, that is, it is fundamentally different from:

StaticArray!(int, 5)

...in that whereas the above code example would _not_ compile, this next example would (and it does) compile:

void foo(T)(T[] da) { }

void bar(int[] da) { }

void main()
{
    int[5] sa;
    bar(sa); // OK: implicit conversion
    foo(cast(int[]) sa); // OK: explicit conversion
    foo(sa); // OK !!! (compare to the previous example)
}
August 15, 2013
On Thursday, 15 August 2013 at 13:50:45 UTC, Maxim Fomin wrote:
> On Thursday, 15 August 2013 at 12:44:09 UTC, Tommi wrote:
>>
>> I don't expect int[3] to implicitly convert to int[] during type deduction for the same reason that I don't expect int to implicitly convert to long during type deduction (even though I know that int implicitly converts to long in all kinds of other contexts):
>>
>> void getLong(T)(T arg)
>> if (is(T == long))
>> {
>> }
>>
>> void main()
>> {
>>    int n;
>>    getLong(n); // int doesn't implicitly convert to long
>> }
>>
>
> OK,
>
> void getLong(T)(T arg)
> if (is(T : long))
> {
> 	
> }
>
> void main()
> {
>     int n;
>     getLong(n); // int is implicitly convertible to long
> }
>
> now you have "implicit conversion from int to long during type deduction".

No it's not:

void getLong(T)(T arg)
if (is(T : long))
{
    static assert(is(typeof(arg) == int));
}

void main()
{
    int n;
    getLong(n); // int is _not_ implicitly converted to long
}
August 15, 2013
On Thursday, 15 August 2013 at 13:53:17 UTC, Artur Skawina wrote:
> On 08/15/13 14:44, Tommi wrote:
> [...]
>> No, I'm not asking A -> C, I'm just asking that int[3] convert to int[].
>
>>From you earlier post:
>
>   Ret bar(R)(R r) // [6]
>   if (std.range.isInputRange!R)
>   {
>       return Ret.input_range;
>   }
>
> You'd like to be able to call 'bar' with a static array. Currently
> you can't, because 'R' becomes a /static array/, hence not a input range.
>
> Note that
>
>   Ret baz(R)(R[] r) // [6]
>   if (std.range.isInputRange!(R[]))
>   {
>       return Ret.input_range;
>   }
>
> [..]

To be exact, I want either of the following options (but not both of them):

1) I want to be able to call 'bar' with a static array

OR

2) I want to _not_ be able to call 'baz' with a static array

Either one of those options is fine by me. All I want is make D's static arrays behave logically (and either one of those options would do it).
August 15, 2013
On Thursday, 15 August 2013 at 14:32:29 UTC, Tommi wrote:
>
> No it's not:
>
> void getLong(T)(T arg)
> if (is(T : long))
> {
>     static assert(is(typeof(arg) == int));
> }
>
> void main()
> {
>     int n;
>     getLong(n); // int is _not_ implicitly converted to long
> }

Yes, because during type deduction there was constraint test that checked whether int is convertible to long which is the same story as in static-dynamic array case.
August 15, 2013
On Thursday, 15 August 2013 at 14:53:08 UTC, Maxim Fomin wrote:
> On Thursday, 15 August 2013 at 14:32:29 UTC, Tommi wrote:
>>
>> No it's not:
>>
>> void getLong(T)(T arg)
>> if (is(T : long))
>> {
>>    static assert(is(typeof(arg) == int));
>> }
>>
>> void main()
>> {
>>    int n;
>>    getLong(n); // int is _not_ implicitly converted to long
>> }
>
> Yes, because during type deduction there was constraint test that checked whether int is convertible to long which is the same story as in static-dynamic array case.

The code snippet above is not the same thing as what happens in the static-dynamic array case. In the above code snippet the type deduction for 'T' during the instantiation of 'getLong' has already finished by the time the template constraint is evaluated (how could the template constraint be evaluated if the actual type for 'T' hadn't already been deduced?). So, the compiler doesn't consider the implicit conversion from int to long _during_ type deduction, but after it.

The only time when the compiler is willing to consider the possible implicit conversions during type deduction is with static arrays: hence... "magic".
August 15, 2013
On Thursday, 15 August 2013 at 15:07:23 UTC, Tommi wrote:
> The only time when the compiler is willing to consider the possible implicit conversions during type deduction is with static arrays: hence... "magic".

Barring this special case which I mentioned in my original post:

On Thursday, 15 August 2013 at 00:57:26 UTC, Tommi wrote:
> NOTE:
> Subtypes can implicitly convert to their supertype during type deduction, there's nothing magical about that.

Here's an example of that:

class SuperClass(T) { }

class SubClass(T) : SuperClass!T { }

struct Supertype(T) { }

struct Subtype(T)
{
    Supertype!T s;
    alias s this;
}

void foo(T)(SuperClass!T superc) { }

void bar(T)(Supertype!T supert) { }

void main()
{
    SubClass!int subc;
    foo(subc); // OK

    Subtype!int subt;
    bar(subt); // OK
}

Although, it might be a bit misleading to call that implicit conversion, because nothing is actually converted: it's just that an entity is interpreted as something else, which it also is.
1 2
Next ›   Last »