[Issue 13196] Infer struct/class template args from constructor args

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Thu Jul 24 23:38:22 PDT 2014


https://issues.dlang.org/show_bug.cgi?id=13196

--- Comment #7 from Manu <turkeyman at gmail.com> ---
(In reply to Jonathan M Davis from comment #6)
> (In reply to Manu from comment #5)
> > (In reply to Jonathan M Davis from comment #4)
> > > Regardless, we can potentially make it so that the compiler is able to infer
> > > the constructor's template arguments for templated types in some basic
> > > cases, but I think that it's clear that we can only do it for a certain
> > > subset.
> > 
> > It's not clear at all. Present a case where it can't work? I haven't seen
> > any yet.
> 
> An obvious case is something like
> 
> struct S(T)
> {
>     this(U)(U u)
>         if(is(U : T))
>     {...}
> 
>     T _t;
> }
> 
> Also, the previous example of
> 
> struct S(T)
> {
>     static if(is(T == bool))
>     {
>         this(T[] t) {}
>     }
>     else
>     {
>         this(int i) {}
>     }
> }

I don't understand why you seem to suggest that either of those cases would be
expected to work? They both make no logical sense.

The first can't possibly deduce T, because U:T is not a 1:1 relationship.

The second is backwards. T must be known to resolve the static if prior to the
constructor existing. So it can't possibly use the constructor to deduce T,
because at the time T must be evaluated, it doesn't exist yet. =

Why would you suggest it's reasonable for people to assume that these should
work?
They're not examples of failing edge cases, they're just nonsense.
Neither case works for functions right now, and so it shouldn't.


> wouldn't work as was previously discussed. The basic case of
> 
> struct S(T)
> {
>     this(T t) {}
> }
> 
> should be possible, but I'd expect that much of anything fancier wouldn't.
> Regardless, the fact that
> 
> struct S(T)
> {
>     this(T t) {}
> }
> 
> is equivalent to
> 
> template S(T)
> {
>     struct S
>     {
>         this(T t) {}
>     }
> }
> 
> is a major hurdle from an implementation point of view, because it would
> mean having to know what was going to be in the template before it's even
> instantiated. Also, you could have something like
> 
> template S(T)
> {
>     struct S
>     {
>         this(int i) {}
>     }
> }
> 
> so the compiler can't assume that the type that's being passed to the
> constructor has anything to do with the template argument.
> 
> When you do S!int(5), the compiler knows the template argument, can
> instantiate the template, and _then_ look at whether trying to call the
> result of the template instantiation with an argument of 5 makes any sense.
> What you're asking for basically requires that the compiler figure out the
> guts of the template before it's even instantiated.

I don't know how the parser works, but I can't imagine that this is challenging
for the parser when considering all the other magic it is capable of. I'd
suspect the parser knows that there is a struct, and that it has a constructor
prior to requiring complete resolution of every detail relating to the struct.

I find it hard to imagine how it's different from the function case.
Is it basically just that the function argument list isn't inside a scope
block,, whereas the constructor is... and you suspect that's a show stopper?

How would forward referencing ever work if the parser isn't capable of
functionality like this?


> I expect that it's
> possible to do that, but it would be a major shift in how templates are
> handled in the compiler, so it wouldn't surprise me at all if it never
> happened, as nice as it would be.

I have no evidence to believe this one way or another. It seems simple enough
though, the logic is obviously implemented for functions, and it should be
basically identical in functionality... I don't see what makes it so difficult
by comparison.

This seems like very easy stuff considering the kind of magic the D parser is
capable of.

--


More information about the Digitalmars-d-bugs mailing list