digitalmars.D.learn - Implicit Template Parameters Cannot Decipher Aliases?
- Vijay Nayar (56/56) Apr 25 2018 I have encountered a problem where whenever I attempt to use a
- Vijay Nayar (2/4) Apr 25 2018
- Simen =?UTF-8?B?S2rDpnLDpXM=?= (34/40) Apr 25 2018 It's a known issue, and could be solved in some cases by partial
- Vijay Nayar (9/12) Apr 25 2018 Ok, wow, you weren't kidding. That becomes really complex really
- Simen =?UTF-8?B?S2rDpnLDpXM=?= (19/32) Apr 25 2018 Right now, yeah, that's probably the most sensible rule to follow.
- ag0aep6g (2/6) Apr 25 2018 https://issues.dlang.org/show_bug.cgi?id=1807
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
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
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
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
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: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: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?https://issues.dlang.org/show_bug.cgi?id=1807Thanks. :) -- Simen
Apr 25 2018
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