www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Serialization/deserialization of templated class

reply Dmitry Solomennikov <dmitrys99 yandex.ru> writes:
Hi, guys!

I have templated classes like this:

class Some(T1) {
   T1 value;
   this(T1 _value){
     value = _value;
   }
}
class Pair(T1, T2) {
   T1 first;
   T2 second;
   this(T1 _first, T2 _second){
     first = _first;
     second = _second;
   }
}

and a lot of serialised data, which I have to read and 
instantiate into given classes.
Serialized data looks like this: 'Some(Pair("df", 5.0))' or 
'Pair(Some(true), 11)', i.e. order of structs, its types and 
inclusion order are unknown at compile time.

I know there are several serialisation libraries, but I found 
they work only with non-templated classes, like:

class Foo {
   int a;
}

I can read input data and parse it, but have no idea how to 
construct object of templated class in this situation. Please 
give a hint.
Jun 27
parent reply Eugene Wissner <belka caraus.de> writes:
On Wednesday, 28 June 2017 at 04:41:25 UTC, Dmitry Solomennikov 
wrote:
 Hi, guys!

 I have templated classes like this:

 class Some(T1) {
   T1 value;
   this(T1 _value){
     value = _value;
   }
 }
 class Pair(T1, T2) {
   T1 first;
   T2 second;
   this(T1 _first, T2 _second){
     first = _first;
     second = _second;
   }
 }

 and a lot of serialised data, which I have to read and 
 instantiate into given classes.
 Serialized data looks like this: 'Some(Pair("df", 5.0))' or 
 'Pair(Some(true), 11)', i.e. order of structs, its types and 
 inclusion order are unknown at compile time.

 I know there are several serialisation libraries, but I found 
 they work only with non-templated classes, like:

 class Foo {
   int a;
 }

 I can read input data and parse it, but have no idea how to 
 construct object of templated class in this situation. Please 
 give a hint.
Templates are a compile time feature. You won't be able to initialize the classes if you don't know the type at compile time. You can use some data structure like Variant that can save values of different types. You could use union for data storage in you class and list all possible types as union members. Probably if you have serialized data, you convert strings to other types, so it may be possible to perfom if-checks: if (myDataIsStringAndDouble(data)) { auto var = new Some!(Pair!(string, double))(new Pair!(string, double)("df", 5.0)); } else if (myDataIsStringAndInt(data)) { auto var = new Some!(Pair!(string, int))(new Pair!(string, int)("df", 5)); }
Jun 27
parent reply Dmitry Solomennikov <dmitrys99 yandex.ru> writes:
On Wednesday, 28 June 2017 at 05:01:17 UTC, Eugene Wissner wrote:
 On Wednesday, 28 June 2017 at 04:41:25 UTC, Dmitry Solomennikov 
 wrote:
 Probably if you have serialized data, you convert strings to 
 other types, so it may be possible to perfom if-checks:
 if (myDataIsStringAndDouble(data))
 {
   auto var = new Some!(Pair!(string, double))(new Pair!(string, 
 double)("df", 5.0));
 }
 else if (myDataIsStringAndInt(data))
 {
   auto var = new Some!(Pair!(string, int))(new Pair!(string, 
 int)("df", 5));
 }
It is possible, but it is not a general solution. I've posted couple of sample classes, but there are more complicated cases, of course, and it well be combinatorial explosion here. I got the Variant idea, I'll give it a try. From other point of view, is there a reflection, say auto i = newInstance("Pair!(int, string)(10, \"asdf\")"), something like in Java?
Jun 27
next sibling parent Eugene Wissner <belka caraus.de> writes:
On Wednesday, 28 June 2017 at 05:52:38 UTC, Dmitry Solomennikov 
wrote:
 On Wednesday, 28 June 2017 at 05:01:17 UTC, Eugene Wissner 
 wrote:
 On Wednesday, 28 June 2017 at 04:41:25 UTC, Dmitry 
 Solomennikov wrote:
 Probably if you have serialized data, you convert strings to 
 other types, so it may be possible to perfom if-checks:
 if (myDataIsStringAndDouble(data))
 {
   auto var = new Some!(Pair!(string, double))(new 
 Pair!(string, double)("df", 5.0));
 }
 else if (myDataIsStringAndInt(data))
 {
   auto var = new Some!(Pair!(string, int))(new Pair!(string, 
 int)("df", 5));
 }
It is possible, but it is not a general solution. I've posted couple of sample classes, but there are more complicated cases, of course, and it well be combinatorial explosion here. I got the Variant idea, I'll give it a try. From other point of view, is there a reflection, say auto i = newInstance("Pair!(int, string)(10, \"asdf\")"), something like in Java?
As far as I know, Java can modify the byte code at runtime. D is a compiled language. It has good compile-time reflection. Anyway you have to find a way to initialize the classes with the types you need. If the type isn't initialized at compile-time, it isn't just there at runtime and can't be used.
Jun 27
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2017-06-28 07:52, Dmitry Solomennikov wrote:
 On Wednesday, 28 June 2017 at 05:01:17 UTC, Eugene Wissner wrote:
 On Wednesday, 28 June 2017 at 04:41:25 UTC, Dmitry Solomennikov wrote:
 Probably if you have serialized data, you convert strings to other
 types, so it may be possible to perfom if-checks:
 if (myDataIsStringAndDouble(data))
 {
   auto var = new Some!(Pair!(string, double))(new Pair!(string,
 double)("df", 5.0));
 }
 else if (myDataIsStringAndInt(data))
 {
   auto var = new Some!(Pair!(string, int))(new Pair!(string,
 int)("df", 5));
 }
It is possible, but it is not a general solution. I've posted couple of sample classes, but there are more complicated cases, of course, and it well be combinatorial explosion here. I got the Variant idea, I'll give it a try. From other point of view, is there a reflection, say auto i = newInstance("Pair!(int, string)(10, \"asdf\")"), something like in Java?
It's possible to instantiate classes using reflection in D, but not for templated classes: class Foo(T) {} class Bar {} void main() { Foo!int a = new Foo!int; Bar b = new Bar; auto o1 = Object.factory("main.Foo!int.Foo"); // does not work for templated classes auto o2 = Object.factory("main.Bar"); // works for non-templated classes assert(o1 is null); assert(o2 !is null); } Actually, if you have the template instantiation available you can do this: Object o = Foo!int.classinfo.create(); -- /Jacob Carlborg
Jun 28
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/28/17 1:52 AM, Dmitry Solomennikov wrote:
 On Wednesday, 28 June 2017 at 05:01:17 UTC, Eugene Wissner wrote:
 On Wednesday, 28 June 2017 at 04:41:25 UTC, Dmitry Solomennikov wrote:
 Probably if you have serialized data, you convert strings to other 
 types, so it may be possible to perfom if-checks:
 if (myDataIsStringAndDouble(data))
 {
   auto var = new Some!(Pair!(string, double))(new Pair!(string, 
 double)("df", 5.0));
 }
 else if (myDataIsStringAndInt(data))
 {
   auto var = new Some!(Pair!(string, int))(new Pair!(string, 
 int)("df", 5));
 }
It is possible, but it is not a general solution. I've posted couple of sample classes, but there are more complicated cases, of course, and it well be combinatorial explosion here. I got the Variant idea, I'll give it a try. From other point of view, is there a reflection, say auto i = newInstance("Pair!(int, string)(10, \"asdf\")"),
No, because the class itself doesn't eixst until you instantiate it. Certainly if you want to write out all the possible instantiations, it's possible, via the mechanisms already specified above. What I would do is create a newInstance *template* that takes a string and generates a function that would build it from that string. Then you can feed a sample file that contains all the possible instantiations to it at *compile time* (via import strings), and then you can automatically build the code that would be able to parse it. Finally, send the real file at runtime.
 something like in Java?
It's important to realize that Java's generics are completely different than D's templates. They are a compile-time wrapping around a runtime construct. Of course, it's possible to mimic Java, but you won't get templates out of it, more like Variant holders. -Steve
Jun 29