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