Error: template instance `Reflect!(type)` cannot use local `type` as parameter to non-global template `Reflect(Ts...)()`

Alex AJ at gmail.com
Sun Apr 7 06:18:51 UTC 2019


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




More information about the Digitalmars-d-learn mailing list