digitalmars.D.learn - Erroneous "auto can only be used for template function parameters"?
- Yuxuan Shui (32/32) Jun 19 2015 Try to compile this code snippet:
- Yuxuan Shui (4/36) Jun 19 2015 Another thing I discovered is instantiation like this: (a!T)!S
- Adam D. Ruppe (8/10) Jun 20 2015 But R is not a parameter on the function itself. It comes from
- Yuxuan Shui (3/13) Jun 20 2015 But surely nested template should be able to access outer
- Steven Schveighoffer (4/20) Jun 22 2015 If you have to instantiate it to see how to instantiate it, it doesn't
- Yuxuan Shui (3/28) Jun 22 2015 I can't see any IFTI in my code, can you point it out?
- Steven Schveighoffer (5/29) Jun 22 2015 Sorry, I misunderstood what is happening here. I don't know what the
- Yuxuan Shui (3/13) Jun 20 2015 Also the same error persists even if I change 'a' to
- Jesse Phillips (21/38) Jun 22 2015 I'm not reproducing in DMD 2.067:
- Yuxuan Shui (22/54) Jun 22 2015 After more experimenting, here's what I got. This time no nested
Try to compile this code snippet: import std.traits; template a(R) { auto a(S)(auto ref R i) { return cast(S)i*2; } } template ReturnTypeEx(alias A, B) { alias ReturnTypeEx = ReturnType!(A!B); } template b(alias R) { int b(S)(S i) { alias Ra = ReturnTypeEx!(R, S); return cast(int)R!S(i); } } void main() { alias bb = b!(a!ulong); pragma(msg, ReturnTypeEx!(bb, int)); } DMD reports: sadf.d(3): Error: auto can only be used for template function parameters sadf.d(8): Error: template instance sadf.a!ulong.A!int error instantiating sadf.d(12): instantiated from here: ReturnTypeEx!(a, int) sadf.d(8): instantiated from here: A!int sadf.d(18): instantiated from here: ReturnTypeEx!(b, int) sadf.d(18): while evaluating pragma(msg, ReturnTypeEx!(b, int)) But a(S)(auto ref R) is indeed a template function, so I don't understand.
Jun 19 2015
On Saturday, 20 June 2015 at 01:50:11 UTC, Yuxuan Shui wrote:Try to compile this code snippet: import std.traits; template a(R) { auto a(S)(auto ref R i) { return cast(S)i*2; } } template ReturnTypeEx(alias A, B) { alias ReturnTypeEx = ReturnType!(A!B); } template b(alias R) { int b(S)(S i) { alias Ra = ReturnTypeEx!(R, S); return cast(int)R!S(i); } } void main() { alias bb = b!(a!ulong); pragma(msg, ReturnTypeEx!(bb, int)); } DMD reports: sadf.d(3): Error: auto can only be used for template function parameters sadf.d(8): Error: template instance sadf.a!ulong.A!int error instantiating sadf.d(12): instantiated from here: ReturnTypeEx!(a, int) sadf.d(8): instantiated from here: A!int sadf.d(18): instantiated from here: ReturnTypeEx!(b, int) sadf.d(18): while evaluating pragma(msg, ReturnTypeEx!(b, int)) But a(S)(auto ref R) is indeed a template function, so I don't understand.Another thing I discovered is instantiation like this: (a!T)!S will result in "C style cast illegal", which is clearly wrong because this is not a cast, (a!T) is not necessarily a type.
Jun 19 2015
On Saturday, 20 June 2015 at 01:50:11 UTC, Yuxuan Shui wrote:auto ref R) is indeed a template function, so I don't understand.But R is not a parameter on the function itself. It comes from the outside template. Move it to the inside template, rewrite it as: auto a(S, R)(auto ref R i) { return cast(S)i*2; } and you should get further.
Jun 20 2015
On Sunday, 21 June 2015 at 01:26:51 UTC, Adam D. Ruppe wrote:On Saturday, 20 June 2015 at 01:50:11 UTC, Yuxuan Shui wrote:But surely nested template should be able to access outer template's parameter.auto ref R) is indeed a template function, so I don't understand.But R is not a parameter on the function itself. It comes from the outside template. Move it to the inside template, rewrite it as: auto a(S, R)(auto ref R i) { return cast(S)i*2; } and you should get further.
Jun 20 2015
On 6/20/15 10:26 PM, Yuxuan Shui wrote:On Sunday, 21 June 2015 at 01:26:51 UTC, Adam D. Ruppe wrote:If you have to instantiate it to see how to instantiate it, it doesn't work. General rule of thumb on templates. IFTI only works at one level. -SteveOn Saturday, 20 June 2015 at 01:50:11 UTC, Yuxuan Shui wrote:But surely nested template should be able to access outer template's parameter.auto ref R) is indeed a template function, so I don't understand.But R is not a parameter on the function itself. It comes from the outside template. Move it to the inside template, rewrite it as: auto a(S, R)(auto ref R i) { return cast(S)i*2; } and you should get further.
Jun 22 2015
On Monday, 22 June 2015 at 13:49:21 UTC, Steven Schveighoffer wrote:On 6/20/15 10:26 PM, Yuxuan Shui wrote:I can't see any IFTI in my code, can you point it out?On Sunday, 21 June 2015 at 01:26:51 UTC, Adam D. Ruppe wrote:If you have to instantiate it to see how to instantiate it, it doesn't work. General rule of thumb on templates. IFTI only works at one level. -SteveOn Saturday, 20 June 2015 at 01:50:11 UTC, Yuxuan Shui wrote:But surely nested template should be able to access outer template's parameter.auto ref R) is indeed a template function, so I don't understand.But R is not a parameter on the function itself. It comes from the outside template. Move it to the inside template, rewrite it as: auto a(S, R)(auto ref R i) { return cast(S)i*2; } and you should get further.
Jun 22 2015
On 6/22/15 1:37 PM, Yuxuan Shui wrote:On Monday, 22 June 2015 at 13:49:21 UTC, Steven Schveighoffer wrote:Sorry, I misunderstood what is happening here. I don't know what the rules are for auto ref for nested template functions, or for explicit instantiation. -SteveOn 6/20/15 10:26 PM, Yuxuan Shui wrote:I can't see any IFTI in my code, can you point it out?On Sunday, 21 June 2015 at 01:26:51 UTC, Adam D. Ruppe wrote:If you have to instantiate it to see how to instantiate it, it doesn't work. General rule of thumb on templates. IFTI only works at one level.On Saturday, 20 June 2015 at 01:50:11 UTC, Yuxuan Shui wrote:But surely nested template should be able to access outer template's parameter.auto ref R) is indeed a template function, so I don't understand.But R is not a parameter on the function itself. It comes from the outside template. Move it to the inside template, rewrite it as: auto a(S, R)(auto ref R i) { return cast(S)i*2; } and you should get further.
Jun 22 2015
On Sunday, 21 June 2015 at 01:26:51 UTC, Adam D. Ruppe wrote:On Saturday, 20 June 2015 at 01:50:11 UTC, Yuxuan Shui wrote:Also the same error persists even if I change 'a' to auto a(S)(auto ref S i)auto ref R) is indeed a template function, so I don't understand.But R is not a parameter on the function itself. It comes from the outside template. Move it to the inside template, rewrite it as: auto a(S, R)(auto ref R i) { return cast(S)i*2; } and you should get further.
Jun 20 2015
On Sunday, 21 June 2015 at 02:37:59 UTC, Yuxuan Shui wrote:On Sunday, 21 June 2015 at 01:26:51 UTC, Adam D. Ruppe wrote:I'm not reproducing in DMD 2.067: void main() { int m; a!int(m); } template a(R) { auto a(S)(auto ref S i) { } } Note that since template 'a' and function template 'a' have the same name you're invoking IFTI, otherwise the code would look like: void main() { int m; z!int.a(m); } template z(R) { auto a(S)(auto ref S i) { } }On Saturday, 20 June 2015 at 01:50:11 UTC, Yuxuan Shui wrote:Also the same error persists even if I change 'a' to auto a(S)(auto ref S i)auto ref R) is indeed a template function, so I don't understand.But R is not a parameter on the function itself. It comes from the outside template. Move it to the inside template, rewrite it as: auto a(S, R)(auto ref R i) { return cast(S)i*2; } and you should get further.
Jun 22 2015
On Saturday, 20 June 2015 at 01:50:11 UTC, Yuxuan Shui wrote:Try to compile this code snippet: import std.traits; template a(R) { auto a(S)(auto ref R i) { return cast(S)i*2; } } template ReturnTypeEx(alias A, B) { alias ReturnTypeEx = ReturnType!(A!B); } template b(alias R) { int b(S)(S i) { alias Ra = ReturnTypeEx!(R, S); return cast(int)R!S(i); } } void main() { alias bb = b!(a!ulong); pragma(msg, ReturnTypeEx!(bb, int)); } DMD reports: sadf.d(3): Error: auto can only be used for template function parameters sadf.d(8): Error: template instance sadf.a!ulong.A!int error instantiating sadf.d(12): instantiated from here: ReturnTypeEx!(a, int) sadf.d(8): instantiated from here: A!int sadf.d(18): instantiated from here: ReturnTypeEx!(b, int) sadf.d(18): while evaluating pragma(msg, ReturnTypeEx!(b, int)) But a(S)(auto ref R) is indeed a template function, so I don't understand.After more experimenting, here's what I got. This time no nested templates are involved, this seems more likely an 'auto ref' bug. import std.traits, std.range; void a(S)(auto ref S i) { } void b(S)(auto ref S i) if (isInputRange!S) { } void c(S)(ref S i) if (isInputRange!S) { } void devil(alias S)() { } void main() { a!string(""); //Works <--- This line affects the result of devil!(a!string) b!string(""); //Works //Next line is weird, it: //1. Err, 'auto ref can only be used with template function', if 'a' is not // instantiated with 'a!string' first //2. Works, if 'a!string' is done first alias x = devil!(a!string); alias xx = devil!(b!string); //Err, template doesn't match alias xxx = devil!(c!string); //Works } I'm using DMD 2.067.1
Jun 22 2015