www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Erroneous "auto can only be used for template function parameters"?

reply "Yuxuan Shui" <yshuiv7 gmail.com> writes:
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
next sibling parent "Yuxuan Shui" <yshuiv7 gmail.com> writes:
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
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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
next sibling parent reply "Yuxuan Shui" <yshuiv7 gmail.com> writes:
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:
 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.
But surely nested template should be able to access outer template's parameter.
Jun 20 2015
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/20/15 10:26 PM, Yuxuan Shui wrote:
 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:
 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.
But surely nested template should be able to access outer template's parameter.
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. -Steve
Jun 22 2015
parent reply "Yuxuan Shui" <yshuiv7 gmail.com> writes:
On Monday, 22 June 2015 at 13:49:21 UTC, Steven Schveighoffer 
wrote:
 On 6/20/15 10:26 PM, Yuxuan Shui wrote:
 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:
 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.
But surely nested template should be able to access outer template's parameter.
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. -Steve
I can't see any IFTI in my code, can you point it out?
Jun 22 2015
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/22/15 1:37 PM, Yuxuan Shui wrote:
 On Monday, 22 June 2015 at 13:49:21 UTC, Steven Schveighoffer wrote:
 On 6/20/15 10:26 PM, Yuxuan Shui wrote:
 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:
 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.
But surely nested template should be able to access outer template's parameter.
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.
I can't see any IFTI in my code, can you point it out?
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. -Steve
Jun 22 2015
prev sibling parent reply "Yuxuan Shui" <yshuiv7 gmail.com> writes:
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:
 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.
Also the same error persists even if I change 'a' to auto a(S)(auto ref S i)
Jun 20 2015
parent "Jesse Phillips" <Jesse.K.Phillips+D gmail.com> writes:
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:
 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.
Also the same error persists even if I change 'a' to auto a(S)(auto ref S i)
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) { } }
Jun 22 2015
prev sibling parent "Yuxuan Shui" <yshuiv7 gmail.com> writes:
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