www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Error: template instance `Reflect!(type)` cannot use local `type` as

reply Alex <AJ gmail.com> writes:
Error: template instance `Reflect!(type)` cannot use local `type` 
as parameter to non-global template `Reflect(Ts...)()`

mixin(`import `~moduleName!(T)~`;`);	
mixin(`alias X = T.`~name~`;`);			
super.Reflect!(X);

I realize X is local but I'm trying to figure out why it can't be 
passed to a "non-global" template.
Apr 06 2019
next sibling parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Sunday, 7 April 2019 at 05:24:38 UTC, Alex wrote:
 Error: template instance `Reflect!(type)` cannot use local 
 `type` as parameter to non-global template `Reflect(Ts...)()`

 mixin(`import `~moduleName!(T)~`;`);	
 mixin(`alias X = T.`~name~`;`);			
 super.Reflect!(X);

 I realize X is local but I'm trying to figure out why it can't 
 be passed to a "non-global" template.
See https://blog.thecybershadow.net/2015/04/28/the-amazing-template-that-does-nothing/ TL;DR At global scope alias Identity(alias X) = X; then where the error is issued from use `Identity!(type)` instead of type.
Apr 06 2019
parent Paul Backus <snarwin gmail.com> writes:
On 4/7/19 1:30 AM, Nicholas Wilson wrote:
 On Sunday, 7 April 2019 at 05:24:38 UTC, Alex wrote:
 Error: template instance `Reflect!(type)` cannot use local `type` as
 parameter to non-global template `Reflect(Ts...)()`

 mixin(`import `~moduleName!(T)~`;`);   
 mixin(`alias X = T.`~name~`;`);           
 super.Reflect!(X);

 I realize X is local but I'm trying to figure out why it can't be
 passed to a "non-global" template.
See https://blog.thecybershadow.net/2015/04/28/the-amazing-template-that-does-nothing/ TL;DR At global scope alias Identity(alias X) = X; then where the error is issued from use `Identity!(type)` instead of type.
This template is actually in Phobos now, as `std.meta.Alias`.
Apr 07 2019
prev sibling parent reply Vladimir Panteleev <thecybershadow.lists gmail.com> writes:
On Sunday, 7 April 2019 at 05:24:38 UTC, Alex wrote:
 Error: template instance `Reflect!(type)` cannot use local 
 `type` as parameter to non-global template `Reflect(Ts...)()`

 mixin(`import `~moduleName!(T)~`;`);	
 mixin(`alias X = T.`~name~`;`);			
 super.Reflect!(X);

 I realize X is local but I'm trying to figure out why it can't 
 be passed to a "non-global" template.
- In DMD, objects may have at most one scope (which can be a class, struct, or stack frame). - Instantiating a template with a scoped object makes the template have the same scope as the object. - If a template is already scoped (non-global), then it thus cannot have a second scope. Hence the error. IIRC there is an experimental pull request which removes this limitation. Workarounds: - Make either the template or the argument global (non-scoped) - Instead of passing the object as a template parameter, pass it as a runtime parameter with a type encapsulating the object. Each runtime parameter may be scoped, thus bypassing the limitation. I'm not sure this applies to your use case, if the Reflect template needs to perform compile-time introspection on the parameter. - If you just need to pass the type, typeof(X) should work of course.
Apr 06 2019
parent Alex <AJ gmail.com> writes:
On Sunday, 7 April 2019 at 05:36:27 UTC, Vladimir Panteleev wrote:
 On Sunday, 7 April 2019 at 05:24:38 UTC, Alex wrote:
 Error: template instance `Reflect!(type)` cannot use local 
 `type` as parameter to non-global template `Reflect(Ts...)()`

 mixin(`import `~moduleName!(T)~`;`);	
 mixin(`alias X = T.`~name~`;`);			
 super.Reflect!(X);

 I realize X is local but I'm trying to figure out why it can't 
 be passed to a "non-global" template.
- In DMD, objects may have at most one scope (which can be a class, struct, or stack frame). - Instantiating a template with a scoped object makes the template have the same scope as the object. - If a template is already scoped (non-global), then it thus cannot have a second scope. Hence the error. IIRC there is an experimental pull request which removes this limitation. Workarounds: - Make either the template or the argument global (non-scoped) - Instead of passing the object as a template parameter, pass it as a runtime parameter with a type encapsulating the object. Each runtime parameter may be scoped, thus bypassing the limitation. I'm not sure this applies to your use case, if the Reflect template needs to perform compile-time introspection on the parameter. - If you just need to pass the type, typeof(X) should work of course.
Ok, When I use typeof(X) the first instance works but then other's end up with junk. This is what I get when I construct the field inside the base class Fields = [ Id = type TypeName = type FullName = mModel.cDerived!(int).type ModuleName = mModel MangledName = _D6mModel__T8cDerivedTiZQm4typeCQBe5cType Protection = public Body = IsZeroInit = false IsTemplate = false Uses = [] Attributes = [] DType = field , Id = testField1 TypeName = testField1 FullName = mModel.cDerived!(int).testField1 ModuleName = mModel MangledName = _D6mModel__T8cDerivedTiZQm10testField1i Protection = private Body = IsZeroInit = false IsTemplate = false Uses = [] Attributes = [sAttributeReflection("XXXRRERES", "string")] DType = field , Id = testField2 TypeName = testField2 FullName = mModel.cDerived!(int).testField2 ModuleName = mModel MangledName = _D6mModel__T8cDerivedTiZQm10testField2d Protection = public Body = IsZeroInit = false IsTemplate = false Uses = [] Attributes = [sAttributeReflection("XXXRRERES4", "string")] DType = field and this is when I construct it then pass it using typeof mixin(`import `~moduleName!(T)~`;`); mixin(`alias TT = `~(T).stringof~`.`~name~`;`); super.Reflect!(typeof(TT)); (the code above is what the base class does, It's essentially moved in to the derived class here) Fields = [ Id = cType TypeName = cType FullName = mModel.cType ModuleName = mModel MangledName = C6mModel5cType Protection = public Body = IsZeroInit = true IsTemplate = false Uses = [] Attributes = [] DType = field , Id = TypeName = int FullName = int ModuleName = MangledName = i Protection = Body = IsZeroInit = true IsTemplate = false Uses = [] Attributes = [] DType = field , Id = TypeName = double FullName = double ModuleName = MangledName = d Protection = Body = IsZeroInit = false IsTemplate = false Uses = [] Attributes = [] DType = field one can see something odd is going on though FullName = mModel.cDerived!(int).type vs FullName = mModel.cType as if the aggregate is being lost. Here is the code: // We let the base class do all work, but must pass in type and name separately //super.Reflect!(T, name); mixin(`import `~moduleName!(T)~`;`); mixin(`alias TT = `~(T).stringof~`.`~name~`;`); pragma(msg, ">>>", T.stringof, " -- ", TT.stringof); super.Reflect!(typeof(TT));
cDerived!int -- type
cDerived!int -- testField1
cDerived!int -- testField2
// Base auto Reflect(Ts...)() { static if (Ts.length > 1) { // Assume field or constructable name is being passed if more than one argument mixin(`import `~moduleName!(Ts[0])~`;`); mixin(`alias T = `~(Ts[0]).stringof~`.`~Ts[1]~`;`); } else alias T = Ts[0]; So, normally, the way that fills out the data correctly, is done by passing T and name(super.Reflect!(T, name)) and then builds the type inside the base reflect. The way that isn't working is building the type in the derived reflect and then passing it using typeof(if direct then the original non-global error occurs). I'm simply trying to factor out that base class from having to build the field and have the field's Reflect function do it. You can find the cod here, but will have to paste in that modified code(the first reflect https://github.com/IncipientDesigns/Dlang_Reflect
Apr 06 2019