www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Instantiate templated class at runtime

reply Aphex <Aphex mail.com> writes:
I have been using Orange SerDes library for an application and 
have run in to a major hurdle. I have the need to SerDes a 
templated class. It seems Orange can only Serialize the class but 
when it attempts to deserialize it at runtime it cannot build the 
class.


It represents the type in the output as `Issue1.Y!string.Y` which 
doesn't even seem right but regardless, it cannot seem to create 
a new instance of Y!T.

I realize that the templates do not probably exist at runtime for 
instantiation and so this is impossible, but Y!string surely does 
exist since I create an object with it(although if separate paths 
exist I could see how it could be an issue).


I need to be able to create such classes because it seems to be 
the only limitation of deseralizing templates:

If, for example, I modify the instance creation code(in 
Reflection.d):

Object newInstance (string name)
{
     auto classInfo = ClassInfo.find(name);

     if (!classInfo)
	{

		if (name == "Issue1.Y!string")
		{
			import Issue1;
			return new Y!string;
		}
		if (name == "Issue1.Y!int")
		{
			import Issue1;
			return new Y!int;
		}

		throw new Exception("Cannot find runtime class information for 
`"~name~"` to instantiate!");

         return null;
	}

     return newInstance(classInfo);
}

and manually create the classes then everything seems to work 
great.


I have a few questions:

1. Is it possible to have a runtime class and struct creator 
function that can deal with templates. It doesn't seem like it 
should be that big a deal. One only needs to actually know the 
size of class and that will depend on the template parameter 
sizes, which if they are known then everything is known?

2. Is the output or Orange for templated classes correct? 
"Issue1.Y!string.Y" or should it be "Issue1.Y!string"? Else this 
is a bug that I'll need to track down and fix.

3. I figure that 1 might be a bit off so I will have to hack the 
code to create a factory to build the various templated types 
I'll use. This is not ideal.

In any case, my feeling is that ClassInfo should handle templated 
classes too.



















-------------- MWE ------------------------


import std.stdio;

import orange.serialization.Serializable : nonSerialized;
import std.file;
import orange.serialization._, orange.serialization.archives._;


class C
{
	int x = 53;
}

class Y(T) : C
{
	T x;

}

int main()
{
	
	
	auto archive = new XmlArchive!(char); // create an XML archive
	auto serializer = new Serializer(archive); // create the 
serializer

	serializer.register!(C);
	serializer.register!(Y!int);
	serializer.register!(Y!string);

	C c = new C();

	C[] ya;
	auto yi = new Y!int;
	yi.x = 22;
	auto ys = new Y!string;
	ys.x = "sfda";
	ya ~= yi;
	ya ~= ys;



	auto slfp = `test.xml`;
	if (!false && exists(slfp))
	{	

		auto f = std.file.read(slfp);
		archive.beginUnarchiving(cast(immutable(void)[])f);
		auto ud = archive.untypedData;

		ya = serializer.deserialize!(C[])(ud);

	} else
	{	
		// write xml file
		archive.beginArchiving();
		std.file.write(slfp, cast(byte[])serializer.serialize(ya));
	}


     return 0;
}
May 26 2019
parent Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Sunday, 26 May 2019 at 17:51:37 UTC, Aphex wrote:
 1. Is it possible to have a runtime class and struct creator 
 function that can deal with templates. It doesn't seem like it 
 should be that big a deal. One only needs to actually know the 
 size of class and that will depend on the template parameter 
 sizes, which if they are known then everything is known?
The root problem is described in https://issues.dlang.org/show_bug.cgi?id=2484. In short, the D runtime keeps track of all class types and lets you search through them and instantiate them if you wish. Sadly, this doesn't cover templated classes, in part because an instantiation of a templated class is not necessarily in the module that defined it, and because there may be multiple identical instantiations across multiple modules. Now, templated classes still have .classinfo members, and these can be used with _d_newclass to create new instances of the class. I filed an issue with Orange for this: https://github.com/jacob-carlborg/orange/issues/57
 2. Is the output or Orange for templated classes correct? 
 "Issue1.Y!string.Y" or should it be "Issue1.Y!string"? Else 
 this is a bug that I'll need to track down and fix.
The name Issue1.Y!string.Y is correct - 'class Y(T) {}' is short for 'template Y(T) { class Y {} }'. -- Simen
May 27 2019