Thread overview
IFTI for constructors worth a DIP?
Mar 30, 2018
Dmitry Olshansky
Mar 30, 2018
Dmitry Olshansky
March 30, 2018
I think it should be mostly stright-forward and we can get rid of “instantiator” functions to do IFTI.

The problem (I guess) is 2 type parameter lists, one of aggregate and the other of function:

struct Foo(T)
if (isSomeSuch!T)
{
    this(U)(T a, U u) if (isSomethindElse!U) {...}
    this(R)(T x, R r) if (yetAnother!U){ ... }
}

I believe in such a case compiler can as far as IFTI goes just consider a combined tuple of types.

Thoughts?
March 30, 2018
On Friday, 30 March 2018 at 06:21:27 UTC, Dmitry Olshansky wrote:
> I think it should be mostly stright-forward and we can get rid of “instantiator” functions to do IFTI.
>
> The problem (I guess) is 2 type parameter lists, one of aggregate and the other of function:
>
> struct Foo(T)
> if (isSomeSuch!T)
> {
>     this(U)(T a, U u) if (isSomethindElse!U) {...}
>     this(R)(T x, R r) if (yetAnother!U){ ... }
> }

More interesting case...
struct Foo(T)
{
     alias K = T.K;
     this(K k) { .... }
     // same
}

In general it might be impossible (if we throw in more static ifs on T’s type) but well IFTI is not 100% solution anyway.

>
> I believe in such a case compiler can as far as IFTI goes just consider a combined tuple of types.
>
> Thoughts?


March 30, 2018
On 3/30/18 2:25 AM, Dmitry Olshansky wrote:
> On Friday, 30 March 2018 at 06:21:27 UTC, Dmitry Olshansky wrote:
>> I think it should be mostly stright-forward and we can get rid of “instantiator” functions to do IFTI.
>>
>> The problem (I guess) is 2 type parameter lists, one of aggregate and the other of function:
>>
>> struct Foo(T)
>> if (isSomeSuch!T)
>> {
>>     this(U)(T a, U u) if (isSomethindElse!U) {...}
>>     this(R)(T x, R r) if (yetAnother!U){ ... }
>> }
> 
> More interesting case...
> struct Foo(T)
> {
>       alias K = T.K;
>       this(K k) { .... }
>       // same
> }
> 
> In general it might be impossible (if we throw in more static ifs on T’s type) but well IFTI is not 100% solution anyway.
> 
>>
>> I believe in such a case compiler can as far as IFTI goes just consider a combined tuple of types.
>>
>> Thoughts?
> 
> 

The easy way to test these is to see what IFTI does now:

import std.traits;

template foo(T)
if (isIntegral!T)
{
    void foo(U)(T a, U u) if (isSomeString!U) {}
}

void main()
{
    foo(1, "hello");
}

onlineapp.d(11): Error: template onlineapp.foo cannot deduce function from argument types !()(int, string), candidates are:
onlineapp.d(3):        onlineapp.foo(T) if (isIntegral!T)

Your second case:

struct Foo(T)
{
     alias K = T.K;
     this(K k) { .... }
     // same
}

I can't see at all how this would work, as there may be infinite types for T that have an alias K that matches.


However, a simpler case:

template foo(T)
{
     alias K = T;
     void foo(K k) {}
}

void main()
{
    foo(1);
}

onlineapp.d(4): Error: undefined identifier K
onlineapp.d(10): Error: template onlineapp.foo cannot deduce function from argument types !()(int), candidates are:
onlineapp.d(1):        onlineapp.foo(T)(K k)

So it appears IFTI wouldn't be up to the task if there are aliases involved, or nested templates. But the simplest cases it does work with:

import std.traits;

template foo(T, U)
if (isIntegral!T && isSomeString!U)
{
    void foo(T a, U u) {}
}

void main()
{
    foo(1, "hello");
}

A class/struct ctor (where the constructor itself isn't a template) isn't any different, I can't see why it wouldn't work.

-Steve