How to get compatible symbol names and runtime typeid names for templated classes?

cc cc at nevernet.com
Tue May 3 13:16:47 UTC 2022


On Tuesday, 3 May 2022 at 10:48:53 UTC, bauss wrote:
> Object.factory calls TypeInfo_Class.find which just loops 
> through ModuleInfo and then looks if any of the entries in 
> localClasses has a name that matches.
>
> Afterwards it calls the create function on the TypeInfo_Class 
> which of course isn't "generic" by any means.
>
> This is where compile-time has its limits compared to runtime 
> type creation, because templates only live during compile-time 
> then it isn't really that easy to do something like this, where 
> it would be trivial in other languages like C#.

On Tuesday, 3 May 2022 at 12:46:56 UTC, Adam D Ruppe wrote:
> On Tuesday, 3 May 2022 at 09:42:45 UTC, cc wrote:
>> something I can pass to `Object.factory`.
>
> Object.factory is useless and will hopefully be removed someday.
>
> Instead, make your own factory registration function.
>
> Put a static constructor in the class which appends a factory 
> delegate to an array or something you can use later. Then you 
> can use your own thing to construct registered objects.

Yeah, that's unfortunate.  Actually I was already doing something 
similar for serialization/encoding to get the true type of an 
object (making sure `Animal an = new Cat();` encodes a Cat and 
not an Animal), took me a second to put two and two together and 
realize I could just instantiate objects via new that way instead 
of calling Object.factory.

At the moment I try to register as many relevant symbols as I can 
automatically when encoding is called for a given object, such as:
```d
private mixin template RegisterModule(alias MOD) {
	void RegisterModule() {
		static foreach (SYM; getSymbolsByUDA!(MOD, Coder)) {
			static if (is(SYM == class)) {
				RegisterSerializer!SYM();
			}
		}
	}
}
private static void[0][string] registeredModules;

private void registerModules(T)() {
	enum string MODULENAME = moduleName!T;
	if (MODULENAME !in registeredModules) {
		registeredModules.require(MODULENAME);
		mixin("import "~MODULENAME~";");
		mixin("mixin RegisterModule!"~MODULENAME~";");
		RegisterModule();
	}
}
IPtr encode(T)(T obj) {
	registerModules!T;
	...
}
```

I'll have to get a little more creative for registering templated 
classes then, something like this works:
```d
static void RegisterSerializer(alias SYM)(string runtimeName = 
null) {
	enum sym = fullyQualifiedName!SYM;
	if (sym !in serialTypes) {
		auto st = new SerialType!SYM;
		serialTypes[sym] = st;
		if (runtimeName.length && runtimeName !in serialTypes)
			serialTypes[runtimeName] = st;
	}
}
static void RegisterSerializer(T : Object)(T obj) {
	RegisterSerializer!T(typeid(obj).name);
}
```
but I'd rather not have to instantiate an actual object just to 
get its typeid().name, I suppose I can just manually construct it 
from the fullyQualifiedName inserting the parenthesis and 
appended portion so it matches.



More information about the Digitalmars-d-learn mailing list