www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Implicit Template Parameters Cannot Decipher Aliases?

reply Vijay Nayar <madric gmail.com> writes:
I have encountered a problem where whenever I attempt to use a 
templated function with alias that partially limits the type of 
the arguments, the program fails to compile.  But if I avoid 
using an alias, the same function can infer all arguments.

Is this working as intended or have I encountered a bug or 
missing feature?

Example below:

```
/**
  * Demonstrate an unexpected compiler error when using implicit 
template parameters
  * combined with aliases to partially instantiate templates.
  */

struct Vector(ElemT, size_t SizeV) {
private:
   ElemT[SizeV] _data;
public:
    property
   ElemT[SizeV] data() {
     return _data;
   }

   ElemT opIndex(size_t i) {
     return _data[i];
   }
}

// A helper alias to partially set a portion of compile-time 
arguments.
template Vector3(ElemT) {
   alias Vector3 = Vector!(ElemT, 3);
}

T addAllWithAlias(T)(Vector3!T v1) {
   T sum = 0;
   foreach (T v; v1.data) {
     sum += v;
   }
   return sum;
}

T addAll(T)(Vector!(T, 3) v1) {
   T sum = 0;
   foreach (T v; v1.data) {
     sum += v;
   }
   return sum;
}

void main() {
   auto v1 = Vector3!double([1.0, 2.0, 3.0]);
   assert(v1[1] == 2.0);

   addAllWithAlias(v1); // Error!
   // template.d(35): Error: template template.addAllWithAlias 
cannot deduce function from
   // argument types !()(Vector!(double, 3LU)), candidates are:
   //   template.d(24):        
template.addAllWithAlias(T)(Vector3!T v1)

   addAll(v1);  // OK.
}
```
Apr 25 2018
next sibling parent Vijay Nayar <madric gmail.com> writes:
On Wednesday, 25 April 2018 at 07:39:28 UTC, Vijay Nayar wrote:
   addAllWithAlias(v1); // Error!
One more note, this following line works correctly.
  addAllWithAlias!double(v1);  // OK.
Apr 25 2018
prev sibling parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Wednesday, 25 April 2018 at 07:39:28 UTC, Vijay Nayar wrote:
 I have encountered a problem where whenever I attempt to use a 
 templated function with alias that partially limits the type of 
 the arguments, the program fails to compile.  But if I avoid 
 using an alias, the same function can infer all arguments.

 Is this working as intended or have I encountered a bug or 
 missing feature?
It's a known issue, and could be solved in some cases by partial template expansion, which is currently not part of the language. I believe it's in bugzilla somewhere, but a cursory search yielded no results. In the general case, the issue is unsolvable, since the relationship between template parameters and alias results may be arbitrarily complex. A simple degenerate case is this: alias Foo(T) = string; T fun(T)(Foo!T a) { return T.init; } unittest { // What's val's type? auto val = fun(""); } Since in this case Foo!T retains no information about T, it's impossible to figure out what T should be. In a more realistic case, where the alias template body includes static ifs, or there are overloads, the relationship is also hard to trace: template Foo(T) if (T.sizeof < 4) { alias T[T.sizeof] Foo; } template Foo(T) if (T.sizeof >= 4) { alias T[T.sizeof/2] Foo; } T fun(T)(Foo!T a) { return T.init; } unittest { int[2] a; auto val = fun(a); } Sure, for a human it's easy to figure out which overload is the right one, but defining the rules such that the compiler can reliably do it is harder. -- Simen
Apr 25 2018
next sibling parent reply Vijay Nayar <madric gmail.com> writes:
On Wednesday, 25 April 2018 at 10:25:11 UTC, Simen Kjærås wrote:
 In the general case, the issue is unsolvable, since the 
 relationship between template parameters and alias results may 
 be arbitrarily complex. A simple degenerate case is this:
Ok, wow, you weren't kidding. That becomes really complex really fast. In that case, is the general rule of thumb that programmers should not use aliases for templated types when specifying template function parameters? No implicit type inference is done on the return type or on local variables, so these alias seem fine enough there. Or should they just be entirely avoided to avoid these kinds of problems?
Apr 25 2018
parent Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Wednesday, 25 April 2018 at 11:26:40 UTC, Vijay Nayar wrote:
 On Wednesday, 25 April 2018 at 10:25:11 UTC, Simen Kjærås wrote:
 In the general case, the issue is unsolvable, since the 
 relationship between template parameters and alias results may 
 be arbitrarily complex. A simple degenerate case is this:
Ok, wow, you weren't kidding. That becomes really complex really fast. In that case, is the general rule of thumb that programmers should not use aliases for templated types when specifying template function parameters? No implicit type inference is done on the return type or on local variables, so these alias seem fine enough there. Or should they just be entirely avoided to avoid these kinds of problems?
Right now, yeah, that's probably the most sensible rule to follow. If someone were to write a DIP, the simple cases (which I'd guess constitute >90% of realistic use cases) could be handled. It would have to be somewhat limited, and identifying a sensible set of limitations would be an important part of the work. I'm not sure exactly what's the best way to implement this - maybe a lowering from auto foo(T)(Vector3!T arg) {} to auto foo(T)(Vector!(T,3) arg) {} That would only work if there's a single overload and no static ifs involved. For a solution that works with static ifs or overloads, something must be done about how the matching itself works. On Wednesday, 25 April 2018 at 11:42:12 UTC, ag0aep6g wrote:
 https://issues.dlang.org/show_bug.cgi?id=1807
Thanks. :) -- Simen
Apr 25 2018
prev sibling parent ag0aep6g <anonymous example.com> writes:
On 04/25/2018 12:25 PM, Simen Kjærås wrote:
 It's a known issue, and could be solved in some cases by partial 
 template expansion, which is currently not part of the language. I 
 believe it's in bugzilla somewhere, but a cursory search yielded no 
 results.
https://issues.dlang.org/show_bug.cgi?id=1807
Apr 25 2018