On Saturday, 31 March 2018 at 13:34:18 UTC, Kagamin wrote:
On Friday, 30 March 2018 at 13:56:45 UTC, Stefan Koch wrote:
Ah that is an interesting bug which further demonstrates that templates are a tricky thing :) Basically you cannot _generally_ proof that one template just forwards to another.
Therefore you have to create separate types.
And since you create separate types the alias is not an alias but a separate template. Solving this may be possible for special cases but in the general case is infeasible.

If a template is used as a type it should be resolved to a type, no? And template resolves to a type in a straightforward way. Where does it fail? Judging by the error message "cannot deduce function from argument types !()(TestType!int)" it does successfully resolve alias to a type.

You're starting in the wrong end - the type cannot yet be considered, since the compiler doesn't know the correct arguments to TestAlias. Given this code:

struct S(T...) {}
alias SS(T...) = S!(T, int);

void foo(T)(SS!T arg) {}

unittest {
    foo(SS!string());
}

The error message is "template foo cannot deduce function from argument types !()(S!(string, int)), candidates are: foo(T)(SS!T arg)".

What the compiler needs to do is figure out what T needs to be in order for SS to return the type S!(int, int). SS hasn't resolved to a type yet at that point, because the compiler has no idea which arguments to give it.

These are the steps the compiler does when it evaluates a function call (simplified):

1) Figure out the overload set.
2) Weed out non-matching overloads.
3) Check that exactly one overload matches*.
4) Use that overload.

In step 2, the compiler looks at the types when the overload is a regular function. When it's a function template, it doesn't know the types yet, and IFTI tries to figure it out by a sort of pattern matching. In the case above, it doesn't find a S!(/*something*/) anywhere, and gives up.

If the compiler were to do something other than give up, we would need some algorithm to define what it should try, and in which order. As human beings, with impressive collections of pattern-matching circuits, we can easily see that it should try putting the first template argument into T. Getting to that conclusion is a lot harder for the poor, stupid compiler.

--
  Simen


*In the case where multiple overloads are a match, the best fit is chosen. If there's more than one best fit, or there's no match, you get a compile error.

Reply via email to