Thread overview
Template Parameter Deduction
Mar 11, 2015
Paul D Anderson
Mar 11, 2015
Paul D Anderson
Mar 11, 2015
Ali Çehreli
Mar 12, 2015
Paul D Anderson
Mar 11, 2015
John Colvin
March 11, 2015
This used to work in D2.065:

given

1) public T mul(T)(in T x, in T y,
    Context context = T.context) if (isDecimal!T)
    // one template parameter for the two input values

and

2) public T mul(T, U)(in T x, U n, Context context = T.context)
    if (isDecimal!T && isIntegral!U)
    // two different template parameters for the two input values

then

3) dec9 arg1 = dec9("1.20");
   long arg2 = 3;
   result = mul(arg1, arg2);
   // correctly deduced function

But now (D2.066.1) either 1) has to be changed to

1) public T mul(T, U)(in T x, U y, Context context = T.context)
    if (isDecimal!T && isDecimal!U)
    // two identical template parameters for the two input values

or 3) has to be changed to

3) dec9 arg1 = dec9("1.20");
   long arg2 = 3;
   result = mul!(dec9,long)(arg1, arg2);
   // template parameters have to be made explicit

Is this expecded behavior?

Paul
March 11, 2015
On Wednesday, 11 March 2015 at 22:44:12 UTC, Paul D Anderson wrote:
> This used to work in D2.065:
>
> given
>
> 1) public T mul(T)(in T x, in T y,
>     Context context = T.context) if (isDecimal!T)
>     // one template parameter for the two input values
>
> and
>
> 2) public T mul(T, U)(in T x, U n, Context context = T.context)
>     if (isDecimal!T && isIntegral!U)
>     // two different template parameters for the two input values
>
> then
>
> 3) dec9 arg1 = dec9("1.20");
>    long arg2 = 3;
>    result = mul(arg1, arg2);
>    // correctly deduced function
>
> But now (D2.066.1) either 1) has to be changed to
>
> 1) public T mul(T, U)(in T x, U y, Context context = T.context)
>     if (isDecimal!T && isDecimal!U)
>     // two identical template parameters for the two input values
>
> or 3) has to be changed to
>
> 3) dec9 arg1 = dec9("1.20");
>    long arg2 = 3;
>    result = mul!(dec9,long)(arg1, arg2);
>    // template parameters have to be made explicit
>
> Is this expecded behavior?
>
> Paul

or *expected* behavior
March 11, 2015
On 03/11/2015 03:44 PM, Paul D Anderson wrote:
> This used to work in D2.065:
>
> given
>
> 1) public T mul(T)(in T x, in T y,
>      Context context = T.context) if (isDecimal!T)
>      // one template parameter for the two input values
>
> and
>
> 2) public T mul(T, U)(in T x, U n, Context context = T.context)
>      if (isDecimal!T && isIntegral!U)
>      // two different template parameters for the two input values
>
> then
>
> 3) dec9 arg1 = dec9("1.20");
>     long arg2 = 3;
>     result = mul(arg1, arg2);
>     // correctly deduced function
>
> But now (D2.066.1) either 1) has to be changed to
>
> 1) public T mul(T, U)(in T x, U y, Context context = T.context)
>      if (isDecimal!T && isDecimal!U)
>      // two identical template parameters for the two input values
>
> or 3) has to be changed to
>
> 3) dec9 arg1 = dec9("1.20");
>     long arg2 = 3;
>     result = mul!(dec9,long)(arg1, arg2);
>     // template parameters have to be made explicit
>
> Is this expecded behavior?
>
> Paul

Hint: It makes it much simpler to work with complete code. The following code took a while for me to put together:

template isDecimal(T)
{
    enum isDecimal = true;
}

template isIntegral(T)
{
    enum isIntegral = true;
}

public T mul(T)(in T x, in T y,
    Context context = T.context) if (isDecimal!T)
    // one template parameter for the two input values
{
    return x;
}

alias Context = int;

public T mul(T, U)(in T x, U n, Context context = T.context)
    if (isDecimal!T && isIntegral!U)
    // two different template parameters for the two input values
{
    return x;
}

struct dec9
{
    string s;
    enum context = 42;
}

void main()
{
    dec9 arg1 = dec9("1.20");
    long arg2 = 3;
    dec9 result = mul(arg1, arg2);
   // correctly deduced function
}

Yes, it fails with 2.066.1 but compiles fine with git head.

Ali

March 11, 2015
On Wednesday, 11 March 2015 at 22:44:12 UTC, Paul D Anderson wrote:
> This used to work in D2.065:
>
> given
>
> 1) public T mul(T)(in T x, in T y,
>     Context context = T.context) if (isDecimal!T)
>     // one template parameter for the two input values
>
> and
>
> 2) public T mul(T, U)(in T x, U n, Context context = T.context)
>     if (isDecimal!T && isIntegral!U)
>     // two different template parameters for the two input values
>
> then
>
> 3) dec9 arg1 = dec9("1.20");
>    long arg2 = 3;
>    result = mul(arg1, arg2);
>    // correctly deduced function
>
> But now (D2.066.1) either 1) has to be changed to
>
> 1) public T mul(T, U)(in T x, U y, Context context = T.context)
>     if (isDecimal!T && isDecimal!U)
>     // two identical template parameters for the two input values
>
> or 3) has to be changed to
>
> 3) dec9 arg1 = dec9("1.20");
>    long arg2 = 3;
>    result = mul!(dec9,long)(arg1, arg2);
>    // template parameters have to be made explicit
>
> Is this expecded behavior?
>
> Paul

This works with 2.066.1 and git HEAD

import std.stdio;
void mul(T)(in T x, in T y, long i = T.init)
if (is(T == int))
{
    writeln("same");
}

void mul(T, U)(in T x, U n, long i = T.init)
if (is(T == int) && is(U == ulong))
{
    writeln("different");
}

void main()
{
    mul(1,2);
    mul(1,2UL);
}


Perhaps there is something important in your incomplete example that I have missed out.
March 12, 2015
On Wednesday, 11 March 2015 at 23:04:15 UTC, Ali Çehreli wrote:
> On 03/11/2015 03:44 PM, Paul D Anderson wrote:
>> This used to work in D2.065:
>>
>> given
>>
>> 1) public T mul(T)(in T x, in T y,
>>     Context context = T.context) if (isDecimal!T)
>>     // one template parameter for the two input values
>>
>> and
>>
>> 2) public T mul(T, U)(in T x, U n, Context context = T.context)
>>     if (isDecimal!T && isIntegral!U)
>>     // two different template parameters for the two input values
>>
>> then
>>
>> 3) dec9 arg1 = dec9("1.20");
>>    long arg2 = 3;
>>    result = mul(arg1, arg2);
>>    // correctly deduced function
>>
>> But now (D2.066.1) either 1) has to be changed to
>>
>> 1) public T mul(T, U)(in T x, U y, Context context = T.context)
>>     if (isDecimal!T && isDecimal!U)
>>     // two identical template parameters for the two input values
>>
>> or 3) has to be changed to
>>
>> 3) dec9 arg1 = dec9("1.20");
>>    long arg2 = 3;
>>    result = mul!(dec9,long)(arg1, arg2);
>>    // template parameters have to be made explicit
>>
>> Is this expecded behavior?
>>
>> Paul
>
> Hint: It makes it much simpler to work with complete code. The following code took a while for me to put together:
>
> template isDecimal(T)
> {
>     enum isDecimal = true;
> }
>
> template isIntegral(T)
> {
>     enum isIntegral = true;
> }
>
> public T mul(T)(in T x, in T y,
>     Context context = T.context) if (isDecimal!T)
>     // one template parameter for the two input values
> {
>     return x;
> }
>
> alias Context = int;
>
> public T mul(T, U)(in T x, U n, Context context = T.context)
>     if (isDecimal!T && isIntegral!U)
>     // two different template parameters for the two input values
> {
>     return x;
> }
>
> struct dec9
> {
>     string s;
>     enum context = 42;
> }
>
> void main()
> {
>     dec9 arg1 = dec9("1.20");
>     long arg2 = 3;
>     dec9 result = mul(arg1, arg2);
>    // correctly deduced function
> }
>
> Yes, it fails with 2.066.1 but compiles fine with git head.
>
> Ali

Thanks to you and John for taking the time to work this out. I didn't mean for anyone to rebuild the example -- I was just hoping there was a quick answer based on known language changes. I should have included complete example code.

At any rate, it looks like there is a hiccup in the template parameter deduction code and that it is being fixed. And it's easy to work around. I'll dig a little deeper to see if I can find a related bug report.

Paul